入口
与上一篇服务注册类似,源码版本2.6.7;消费端对象生成代理对象入口也是
com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
这里我们只分析
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
进一步我们找到消费端代理生成的关键类
com.alibaba.dubbo.config.spring.ReferenceBean
这里我们看到 ReferenceBean也是实现了InitializingBean,那么afterPropertiesSet就是框架的关键
调用流程
我们跟踪代码调用流程,紧接着是一系列的检查
com.alibaba.dubbo.config.spring.ReferenceBean#getObject
↓
com.alibaba.dubbo.config.ReferenceConfig#get
↓
com.alibaba.dubbo.config.ReferenceConfig#init
init方法首先是一系列的检查,这个方法比较长;主要做一些检查,然后把需要的属性放入到map中,用于后期代理对象的创建;
↓
com.alibaba.dubbo.config.ReferenceConfig#createProxy
代码跟踪到397行
if (urls.size() == 1) {
invoker = refprotocol.refer(interfaceClass, urls.get(0));
} else {
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // use last registry url
}
}
if (registryURL != null) { // registry url is available
// use AvailableCluster only when register's cluster is available
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // not a registry url
invoker = cluster.join(new StaticDirectory(invokers));
}
}
这里的 urls 是与我们消费端 dubbo:registry标签对应的,可以配置多个,那么这个地方size就大于1了
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
以上是dubbo源码里的demo配置做了稍微修改
通过debug发现,urls里元素的 protocol都是 Registry,说明 调用refprotocol(Protocol$Adaptive的实例)将会调用 RegistryProtocol 的refer方法;这里是不是很熟悉,在服务发布的代理里也是首先调用了RegistryProtocol 的export方法,再调用具体Protocol的export方法,消费端处理流程也是这样的,只不过调用的方法是refer;
所以,dubbo内部是以注册中心为驱动的
下面就是一系列消费端代理生成,与服务端建立长连接,订阅zookeeper等逻辑