Dubbo定义的元素注册到Spring容器的原理解析

Spring对第三方自定义元素配置的支持
  1. Spring中bean的定义可以通过编程,可以定义在properties文件,也可以定义在通过xml文件中,用的最多的是通过xml形式,由于xml格式具有很好的自说明便于编写及维护。对于xml的文档结构、数据定义及格式验证可以通过DTD和Schema, 在spring2.0之前采用的是DTD,在spring2.0之后采用Schema。使用Schema方式使得spring更加便于与第三方进行集成以及第三方可以提供更简单更便于使用的个性化配置方式。
    对于XmlSchema,有个重要的概念命名空间(namespace)必须要提一下,spring就是利用它来做第三方自定配置格式的解析的,在spring中aop, transaction的就是一个实现自己自定义配置很好实例。
    这里写图片描述
    如上图:xmlns=http://www.springframework.org/schema/beans是默认命名空间
    xmlns:aop=http://www.springframework.org/schema/aop 定义的aop的命名空间
    xmlns:tx=”http://www.springframework.org/schema/tx” 定义了事物的命名空间
  2. spring通过schema方式来解析配置文件的基本原理:
    类DefaultBeanDefinitionDocumentReader会把spring的xml配置文件当做一个文档格式来读取。
    这里写图片描述
    每读取一个元素节点都会判断下这个元素的命名空间,如果是默认命名空间(http://www.springframework.org/schema/beans)则按默认方式读取bean的定义。如果不是如namespaceUri如下:
    http://www.springframework.org/schema/aop,
    http://www.springframework.org/schema/tx,
    http://code.alibabatech.com/schema/dubbo
    则走解析自定义元素流程。根据命名空间去获取具体的处理器NamespaceHandler
    这里写图片描述
    DefaultNamespaceHandlerResolver类传了key为namespaceUri,在类中有个Map存储类所有的自定义NamespaceHandler,这个Map中的值是通过工具类PropertiesLoaderUtils加载所有在”META-INF/spring.handlers”中的值
    这里写图片描述
    这里写图片描述
解析Dubbo自定义的元素到注册Spring容器中

这里写图片描述
DubboNamespaceHandler中注册了这么多的BeanDefinitionParser用来解析dubbo定义的那些xml元素节点如:

<dubbo:application name="dubbo-admin" />
<dubbo:registry address="${dubbo.registry.address}" check="false"file="false" />
<dubbo:reference id="registryService"interface="com.alibaba.dubbo.registry.RegistryService"check="false" />
<dubbo:reference id="demoService"interface="com.alibaba.dubbo.demo.DemoService" />
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService"ref="demoService" />

各个BeanDefinitionParser会把上面的xml元素转换成spring内部的数据结构BeanDefinition,最终当被引用时实例化成对应的bean如<dubbo:application/>节点得到ApplicationConfig。当然通过默认配置方式也是可以的如:

<dubbo:registry address="${dubbo.registry.address}" check="false"file="false" />

也可以配置成

<bean id="registry" class="com.alibaba.dubbo.config.RegistryConfig"/>
    <property name="address" value="${dubbo.registry.address}"/>
    <property name="check" value="false"/>
    <property name="file" value="false"/>
<bean/>

利用自定义元素解析更加简洁,同时也可以屏蔽一些具体的实现类型,如你不需要知道com.alibaba.dubbo.config.RegistryConfig这个类,只需要知道注册registry这个元素就可以了,用户可以通过文档以及schema的在ide中的自动提示可以很方便的去配置。