真*dubbo 源码分析(一)

这一部分主要是解析dubboxml 的标签,以及referenceBean的动态代理,注册zkclient 以及zk 的监听器

个人理解,如有不对还望指出,一同进步

首先,根据dubbo 自定义的继承于namespacehandlesupport 将会去解析 dubbo xml 里面的各个标签。 为什么会提交给namespacehandlesupport 呢?准确的说应该是dubbonamespacehandle 。  因为在dubbojar 包下面有个META-INF 下面有个spring.handlers spring.schemas, handler 里面写着交给哪个类去处理,schemas 顾名思义是标签的规则。

真*dubbo 源码分析(一)

当运行dubbo 项目的时候, 他就会先跳到DubboNamespaceHandler 

真*dubbo 源码分析(一)

这个里面的init()方法中 会把各种标签都交给DubboBeanDefinitionPaser 处理,每一个标签就会掉对应的elementName’方法一次,这里elementName的意思是图上registerBeanDefinitionParser()方法的第一个参数。这里经过老师的讲解,觉得这里做的不好,因为全部交给DubboBeanDefinitionParser来做的话里面会有很多的判断。

用来判断很多的类型等等,所以觉得应该这样写比较好

真*dubbo 源码分析(一)

每个标签交给不同的解析类去解析,可读性会好一点。

之后跳到DubbobeanDefinationParse中的parse方法

真*dubbo 源码分析(一)

Element 就是dubbo xml 中的元素标签,parserContext是我们等会要注入的springioc容器

beanClass我刚开始以为是interface 后来发现实际上是dubbo标签的类型class com.alibaba.dubbo.config.ConsumerConfig比如这个, 实际上是上上图的registerBeanDefinitionParser()方法中第二个参数的 参数的类的全路径名。

如果我配置了一个<dubbo:reference id="userDao" interface="mydubboprovide.UserDao" check="false" />

那么beanClass就是class com.alibaba.dubbo.config.spring.ReferenceBean, id就是userDao

真*dubbo 源码分析(一)

这边一个判断是看看springioc 容器中有没有和这个id 一样的 没有的话就将id作为key放进去,beanDefinition 作为value 这样就注入了spring 容器中了。

其他的属性 interface也是通过这个方法将属性注入beanDefinition中,然后

真*dubbo 源码分析(一)

从com.alibaba.dubbo.config.spring.ReferenceBean拿到所有的方法,找到已set方法开头的方法, 说白了 这就是set注入。 你如有个setInteface方法, 那么他会获得这个方法的参数属性, 并且用beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);拿到与之匹配的get方法。但是get方法就判断了是不是空,修饰符是否为public 判断完了continue;完全看不懂有什么用。

真*dubbo 源码分析(一)

Set后面跟的方法名字不是图上那三个的话, 直接从标签上面取得,

之后会调到referenceBean 的 实现类InitializingBeanafterPropertiesSet()方法。顾名思义实在属性设置完成后调到这个方法的。这个方法我看了一下就是设置zk 注册地址,monitor 等等。然后继续走

实现类的FactoryBean getObject()方法。

这是做什么呢?实际上返回了一个ReferenceBean的代理实例。即对ReferenceBean的动态代理。走到get()方法里面发现里面有个appendPropertiesconfig)方法config是这个 <dubbo:reference singleton="true" interface="mydubboprovide.UserDao" generic="false" check="false" id="userDao" />

 

里面通过这个方法又开始找set方法, 和上面一样,只不过如果system里面有就调用method.invoke方法貌似。 (这个不太清楚)。

再回到init()方法中 他将renference中的各个属性啊比如interface id interface中的method等等 放入一个map中然后去调用createproxy 方法,其实是将全局配置加载进map中然后传过去。createproxy 方法中会先看看是不是injvm的,如果是就本地调用。不是的话然后会看到有个loadRegistry方法。里面会将zk 地址放入到registries中。有个UrlUtils.parseURLs(address, map)方法这个会拼装出一个Url, 然后如果修改zk协议为registry协议。(就是url本来是zookeeper://.... 变成了 registry://....)并且是协议中多个属性 registry=zookeeper;

 

然后在给monitorcreateproxymap)方法中的map 放入url.

真*dubbo 源码分析(一)

然后在调用 refprotocol;

真*dubbo 源码分析(一)

Refprotocol运用了spi 技术。

这里urlregistry 开头所以调到了registryProtocolrefer方法。

真*dubbo 源码分析(一)

,这里先看看有没有registry参数,会发现registry=zookeeper,然后移除registry参数,url变成了zookeeper://...

这里的registryFactory.getRegistry(url) 后面就是建立zk 链接了。

这里面首先会尝试着从缓存中看看有没有这个值,首次当然是没有

那么就调用createRegistry()

真*dubbo 源码分析(一)

这个方法会调到ZookeeperRegistry();zookeeperTransporter 怎么来的呢? spi

真*dubbo 源码分析(一)

zookeeperTransporter.connect(url),这个跟了一下,结合addStateListener看 贼有意思。

zookeeperTransporter.connect(url)意思就是新建一zkclient

真*dubbo 源码分析(一)

这边 很明显匿名内部类,clientsubscribeStateChange 会把这个监听器放入zkClient 的 一个Set 中,这个Set 专门用来存储注册进来的监听器。stateChanged 方法执行后会遍历Set,每个监听器都调用他的statechanged方法 handlenewSession 说明session 不一样了, 那不就是断了要重新连了么, statechanged 方法就会调到上上图的recover方法。我们回到进来的refer方法,往下走doRefer

真*dubbo 源码分析(一)

再往下就是zk notify 了。以后写