dubbo实现简析(3)

前文讲述了<dubbo:service interface="" ref="">的暴露服务的过程,下面讲讲consumer怎么使用<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" >怎么调用这个暴露出的服务。

1)解析ReferenceBean的各种属性的过程是类似的:
 String value = element.getAttribute(property);
Object reference = new RuntimeBeanReference(value);
beanDefinition.getPropertyValues().addPropertyValue(property, reference);

public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean
我们看到 ReferenceBean还实现了FactoryBean接口(getObject等方法),这显然是必须的,ReferenceBean不就是要拿到远程服务对象的代理嘛。查看代码,是的,这个 getObject方法正是入口。
T ref = createProxy(map);
return ref;


2)来看看createProxy(map):
if (isJvmRefer) {//默认情况下如果本地有服务暴露,则引用本地服务.
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
invoker = refprotocol.refer(interfaceClass, url);
          
} else { 
     invoker = refprotocol.refer(interfaceClass, urls.get(0));//先看单个的,cluster无非是根据策略从多个中选一个
}
// 创建服务代理
        return (T) proxyFactory.getProxy(invoker);//此方法在2中已列出,这里不再重复分析。
这样,客户consumer程序就可以利用代理调用目标对象的方法了。


3)具体分析一下拿到invoker的过程: refprotocol.refer(interfaceClass, url);
public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException {
        final Invoker<T> tagert = proxyFactory.getInvoker(doRefer(type, url), type, url);
        Invoker<T> invoker = new AbstractInvoker<T>(type, url) {
            @Override
            protected Result doInvoke(Invocation invocation) throws Throwable {
                try {
                    Result result = tagert.invoke(invocation);
                    Throwable e = result.getException();
                    if (e != null) {
                        for (Class<?> rpcException : rpcExceptions) {
                            if (rpcException.isAssignableFrom(e.getClass())) {
                                throw getRpcException(type, url, invocation, e);
                            }
                        }
                    }
                    return result;
                } catch (RpcException e) {
                    if (e.getCode() == RpcException.UNKNOWN_EXCEPTION) {
                        e.setCode(getErrorCode(e.getCause()));
                    }
                    throw e;
                } catch (Throwable e) {
                    throw getRpcException(type, url, invocation, e);
                }
            }
        };
        invokers.add(invoker);
        return invoker;
    }


protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException {
        final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
        rmiProxyFactoryBean.setServiceUrl(url.toIdentityString());
        rmiProxyFactoryBean.setServiceInterface(serviceType);
        rmiProxyFactoryBean.setCacheStub(true);
        rmiProxyFactoryBean.setLookupStubOnStartup(true);
        rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true);
        rmiProxyFactoryBean.afterPropertiesSet();
        return (T) rmiProxyFactoryBean.getObject();
    }
仍然以rmi协议为例,这里用了spring里线程的RmiProxyFactoryBean来生成rmi协议的代理对象。
如果是自定义协议如dubbo,那就得自行实现类似的过程。我们下一节准备来看看dubbo协议的export(), refer()的实现

转载于:https://my.oschina.net/u/603187/blog/552064

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值