dubuo:* 标签的DTD文件的引用位置
在dubbo-2.6.9.jar包下的META-INF文件下的spring.schemas有配置
spring解析xml会利用spi机制到指定目录的该文件下加载dtd文件,约束dubuo:*的使用格式
![](https://img.haomeiwen.com/i23353704/b8784eae198e36e1.png)
1. dubbo:*标签的解析入口
在spring的自定义标签解析中,会同样利用spi机制加载META-INF/spring.handles文件,解析原理和Spring解析的配置文件中的ComponentScan标签一样
https://note.youdao.com/s/DmXioh3u
该文件的内容是标签的uri对应一个NamespaceHandlerSupport的实现类DubboNamespaceHandler
![](https://img.haomeiwen.com/i23353704/c427735745e0f238.png)
DubboNamespaceHandler重写父类NamespaceHandlerSupport的init()方法,init方法会作为一个钩子方法,在spring解析xml文件的过程中被调用到,用于初始化标签与标签的解析器的对应关系。解析某个标签时,会调用BeanDefinitionParser的实现类的parse()来完成解析工作。
这里除了 <dubbo:annotation>标签的解析类是AnnotationBeanDefinitionParser类之外,其余所有的标签都是由
DubboBeanDefinitionParser类来完成的
![](https://img.haomeiwen.com/i23353704/47a7279e8af9eaa6.png)
并且DubboBeanDefinitionParser的初始化的时候,往构造方法传入配置类 ***Config类,用来装标签解析出来的配置信息,比如ServiceBean的父类ServiceConfig,类的属性与配置属性一一对应
![](https://img.haomeiwen.com/i23353704/fae25ff589f44780.png)
2. DubboBeanDefinitionParser解析
DubboBeanDefinitionParser负责解析以下标签
- application
- module,
- registry
- monitor,
- provider
- consumer
- protocol
- service,
- reference
2.1 registry标签的解析
用法 :
<!-- 指定zookeeper作为服务的注册中心,并声明zookeeper的ip和端口 -->
<dubbo:registry check="false" address="zookeeper://192.168.31.211:2181"/>
DubboBeanDefinitionParser对于<registry>b标签的解析parse方法
- 创建RootBeanDefinition
- beanClass为标签对应的解析类的beanClass对象
通过构造方法传进来了
![](https://img.haomeiwen.com/i23353704/dc3ea6f9b5ad20d7.png)
设置BeanDefinition的BeanClass为RegistryConfig类型
![](https://img.haomeiwen.com/i23353704/75700ee691944687.png)
- bean的id为RegistryConfig的全限定性类型com.alibaba.dubbo.config.RegistryConfig
![](https://img.haomeiwen.com/i23353704/67850fdf82b7b715.png)
- 将<RegistryConfig>标签解析出来的属性放到BeanDefinition的PropertyValues中
![](https://img.haomeiwen.com/i23353704/f9d1b5eb474d8dda.png)
spring 在实例化RegistryConfig对象的时候,会通过这个PropertyValues的propertyValueList根据name,value设置到RegistryConfig对象的id,check,address属性中去。
5.坐等spring实例化 RegistryConfig
3. AnnotationBeanDefinitionParser解析<dubbo:annotation>
用法:用于扫描某个包下的@Service注解,将含有该标签的类实例化,并暴露该服务到zookeeper中以供其他服务调用
<dubbo:annotation package="com.lb.dubbo_api.service" />
![](https://img.haomeiwen.com/i23353704/14140bafdee5b263.png)
3.1 AnnotationBeanDefinitionParser解析工作
![](https://img.haomeiwen.com/i23353704/155a571183ea3cda.png)
类方法中并未重写顶级父类AbstractBeanDefinitionParser的parse方法,
而是重写了doParse(),方法用于在顶级父类parse()构建BeanDefination的过程中,利用钩子方法设置bean实例化构造器的参数,其实就是标签里的package属性。
最后一行代码还注册了ReferenceAnnotationBeanPostProcessor的beanDefinition
![](https://img.haomeiwen.com/i23353704/2dd2d344a9999de8.png)
![](https://img.haomeiwen.com/i23353704/d35aef4f59b9bf14.png)
![](https://img.haomeiwen.com/i23353704/35a5893bc9cc407a.png)
![](https://img.haomeiwen.com/i23353704/2dae1490b0eddbf7.png)
以及重写了getBeanClass(),方法返回ServiceAnnotationBeanPostProcessor类的class对象,其实就是返回用于设置BeanDefination的beanClass属性。
![](https://img.haomeiwen.com/i23353704/125733cbc371c762.png)
3.2 调用流程
Spring解析xml先调用顶级父类的AbstractBeanDefinitionParser的parse方法
parse方法中调用直接父类AbstractSingleBeanDefinitionParser的parseInternal(),
![](https://img.haomeiwen.com/i23353704/fdc7770f7175daa1.png)
AbstractSingleBeanDefinitionParser的parseInternal()
先是调用AnnotationBeanDefinitionParser重写的钩子方法getBeanClass(),返回的类型为ServiceAnnotationBeanPostProcessor
![](https://img.haomeiwen.com/i23353704/97aebdc10323b39f.png)
钩到AnnotationBeanDefinitionParser.getBeanClass()
![](https://img.haomeiwen.com/i23353704/8a1f21dd942b059a.png)
设置到BeanDefinatio的beanClass属性中
![](https://img.haomeiwen.com/i23353704/40048291d8fa670d.png)
钩到AnnotationBeanDefinitionParser的doParse()方法
![](https://img.haomeiwen.com/i23353704/380d380c5ef20f4e.png)
![](https://img.haomeiwen.com/i23353704/a92ae8f4be1b76aa.png)
3.3 总结
就是注册了两个类的BeanDifinition
ReferenceAnnotationBeanPostProcessor
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcessor为BeanDefinitionRegistryPostProcessor类型,ioc实例化时,会先调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。
![](https://img.haomeiwen.com/i23353704/d4d24c3eb0d34378.png)
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcessor为BeanDefinitionRegistryPostProcessor类型,ioc实例化时,会先调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。
![](https://img.haomeiwen.com/i23353704/a671f3a8ee8a9d99.png)
ServiceAnnotationBeanPostProcessor.postProcessBeanDefinitionRegistry用于创建扫描器,扫描指定package中含有@Service注解的类,并创建其BeanDefinition,用于后期实例化
![](https://img.haomeiwen.com/i23353704/2b027af0f7c5cc45.png)
![](https://img.haomeiwen.com/i23353704/451dbd36f900ef2a.png)
扫描包得到的beanDefinitionHolders,循环,获取其接口类型,并根据@Service注解里的值创建一个新AbstractBeanDefinition。因为消费者rpc调用时是根据接口类型调用。
![](https://img.haomeiwen.com/i23353704/998760d26ee2c808.png)
![](https://img.haomeiwen.com/i23353704/1e7fe92d1f69a027.png)
将service注解指定的属性值设置到beanDefinitionHolders的属性中
![](https://img.haomeiwen.com/i23353704/19c48e5e74b64ecd.png)
属性设置好之后,注册
![](https://img.haomeiwen.com/i23353704/36600ef51ef0181f.png)
ReferenceAnnotationBeanPostProcessor
其继承 AnnotationInjectedBeanPostProcessor类,是一个BeanPostProcessor类型。对实例化后的每一个Bean中含有@Reference的属性进行注入。因为涉及到rpc远程调用的代理服务对象,后续再讲。
![](https://img.haomeiwen.com/i23353704/c2b0e8aa37561296.png)
网友评论