前言
前面几篇关于dubbo的文章一直都是介绍服务暴露,这篇文章就来说说服务的引用。
源码构成
先来一张官方文档上的图
看代码最重要的一步就是找到代码的起点,服务消费的起点就是dubbo-demo-cosumer.xml文件
1 | <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> |
通过spring的schemas标签引用服务,和服务暴露的时候一样,我们找到DubboNameSpaceHandler文件,即dubbo的命名空间处理器,找到dubbo:reference标签解析。
DubboNamespaceHandler类
1 | public void init() { |
ReferenceBean类
观察到ReferenceBean类继承了FactoryBean类,而spring中的FactoryBean类就是用于获取动态代理对象的。所以我们就dubug进入ReferenceBean继承FactoryBean实现的getObject()方法里面看看。
1 | public Object getObject() throws Exception { |
ReferenceConfig类
get()
1 | public synchronized T get() { |
init()
–>createProxy()
1 | // 通过refer创建invoker对象 |
–>ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(“registry”);
–>extension.refer(arg0, arg1);
–>ProtocolFilterWrapper.refer
–>RegistryProtocol.refer ——建立zk连接
1 | public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { |
doRefer()——创建、订阅节点
1 | private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) { |
registry.register//创建zk的节点,和服务端发布一样(省略代码)。节点名为:dubbo/com.alibaba.dubbo.demo.DemoService/consumers
registry.subscribe//订阅zk的节点,和服务端发布一样(省略代码)。 /dubbo/com.alibaba.dubbo.demo.DemoService/providers,
/dubbo/com.alibaba.dubbo.demo.DemoService/configurators, /dubbo/com.alibaba.dubbo.demo.DemoService/routers]
当然这里说到了服务的发布和引用在建立zk连接,创建节点以及订阅节点都是一样的。有没有不同之处呢?还是有的,就是在订阅结束之后的通知环节。
zookeeperRegistry().doSubscribe()
–>FailbackRegistry.notify
-->doNotify(url, listener, urls);
-->AbstractRegistry.notify
–>saveProperties(url);//把服务端的注册url信息更新到C:\Users\bobo.dubbo\dubbo-registry-192.168.48.117.cache
–>registryCacheExecutor.execute(new SaveProperties(version));//采用线程池来处理
–>listener.notify(categoryList)
以上的通知流程都是和服务发布的时候是一样的,直到进入
RegistryDirectory.notify
1 | refreshInvoker(invokerUrls)//刷新缓存中的invoker列表 |
refreshInvoker的最终目的:刷新Map<String, Invoker
ok,上面的所有代码就完成了scheemas标签信息到invoker的转换,下面就来将invoker到ref的转换过程——就是创建代理。
再回到createProxy()
1 | // 创建服务代理 |
–>ProxyFactory$Adpative.getProxy
-->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension("javassist");
-->StubProxyFactoryWrapper.getProxy
-->proxyFactory.getProxy(invoker)
-->AbstractProxyFactory.getProxy
-->getProxy(invoker, interfaces)
JavassistProxyFactory类
1 | public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { |
Proxy.getProxy(interfaces)//目前代理对象interface com.alibaba.dubbo.demo.DemoService, interface com.alibaba.dubbo.rpc.service.EchoService
InvokerInvocationHandler// 采用jdk自带的InvocationHandler,创建InvokerInvocationHandler对象。