dubbo原理之标签解析

前言:dubbo的标签解析作为dubbo的入口,结合spring容器的一小小部分的流程,让大家了解以下dubbo的服务提供者在将服务暴露之前,经历了哪些过程。
标签解析主要是spring的源码部分,spring源码加注解部分我也上传github了https://github.com/lengweijian/spring-framework.git. 5.0.x分支。

下边是伪代码,想调试的也可以按照下面的思路打断点调试。

refresh()
—> obtainFreshBeanFactory()
—> refreshBeanFactory()
—> AbstractRefreshableApplicationContext.loadBeanDefinitions()
—> 1.XmlBeanDefinitionReader.doLoadDocument() [加载xml文件内的标签元素返回Document]
—> 2.XmlBeanDefinitionReader.registerBeanDefinitions() [注册bd]
—> 3.创建XmlReaderContext -------DefaultNamespaceHandlerResolver 创建默认的namespace处理器 [默认的处理器在META-INF/spring.handlers路径下]
—> 4.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions() [注册bd]
—> 5.判断是不是默认的解析器,如果是:
----> 5.1 预处理xml preProcessXml()
----> 5.2 解析parseBeanDefinitions()
—> 5.2.1 解析bd的时候会判断每个跟元素是不是默认的namespace,如果是,解析默认的namespace
—> 5.2.2 不是默认的namespace,走自定义的BeanDefinitionParserDelegate.parseCustomElement()
—> 5.2.2.1 先获取namespaceUri. [http://dubbo.apache.org/schema/dubbo]
—> 5.2.2.2 DefaultNamespaceHandlerResolver.resolve()
—> 5.2.2.1 获取handlerMappings 包括DubboNamespaceHandler全路径名
—> 5.2.2.2 根据全路径名利用反射,创建对象 DubboNamespaceHandler
—> 5.2.2.3 利用对象调用DubboNamespace的init();
—> 5.2.2.3.1 NamespaceHandlerSupport.registerBeanDefinitionParser() [作用是将标签和XXXConfig类做一个映射放进Map<String, BeanDefinitionParser> parsers里面]
—> 在解析到service标签的时候,会创建ServiceBean的对象,由于这个对象实现了很多spring的生命周期接口。和监听接口。InitializingBean\DisposableBean\ApplicationListener
—> 5.2.2.3.1.1 ServiceBean.afterPropertiesSet() [在这个方法里面执行服务的暴露操作export()]

下面是一个很不直观的流程图,其实画时序图更好一些,有时间补上。

dubbo原理之标签解析

总结dubbo标签解析:

1.因为dubbo的xml形式是属于自定义的namespace的标签(比如:<dubbo:xxxxxx />),所以dubbo做了这几件事:

在dubbo-config模块下创建了/META-INF/dubbo.xsd文件(里面自定义了dubbo xml风格在spring配置文件里面的dtd规则,以及每个标签是由哪个XXXConfig类来封装的标签属性。比如:dubbo:application 映射–→ ApplicationConfig.java).
在dubbo-config模块下创建了/META-INF/spring.handlers文件,里面定义了DubboNamespaceHandler.java类,类图如下。像其他自定义的命名空间一样,像自定义命名空间风格,就可以继承NamespaceHandlerSuport类,重写init()方法。
dubbo原理之标签解析
2.spring容器启动后会加载provider-xml-application.xml文件,然后会使用document例如dom4j技术解析xml文件,解析前会根据dubbo原理之标签解析
寻址,校验这个xml文件里面的标签属性合不合法,校验通过后就开始注册BeanDefinition,首先会根据BeanDefinitionParserDelegate判断Domcument里面的每个element元素是不是自定义的标签,如果是,就是使用bdParserDelegate来获取namespaceUri字符串,使用DefaultNamespaceHandlerResolver来resolve解析namespaceUri字符串,解析的时候会先获取处理器映射(这11个entity是当前ioc容器里所有的自定义的dtd和NamespaceHandler处理器的映射。
dubbo原理之标签解析
由于当前的namespaceUri是dubbo原理之标签解析
,所以可以get到一个org.apache.dubbo.config.spring.schema.DubboNamespaceHandler的全路径名,再通过反射创建
NamespaceHandler类型的对象,有了NamespaceHandler对象,就可以执行dubbo原理之标签解析
里面的init()方法,这里是重点!!!!!!
由于我们是自定义的DubboNamespaceHandlerdubbo原理之标签解析
,所以会执行HandlerNamespaceHandler的init()方法,如下图:
dubbo原理之标签解析
由于我们现在分析的是服务的提供者,所以可以看到ServiceBean.java
dubbo原理之标签解析
里面实现了几个比较重要的接口,由于ServiceBean监听的是ContextRefreshedEvent容器刷新事件,所以在容器刷新结束后会执行onApplicationEvent()的回调方法,在方法里面判断如果当前服务没有被暴露并且希望被暴露,就会执行暴露服务export()。【有关于服务暴露的原理,会在下一节叙述。】
dubbo原理之标签解析
等服务暴露结束后,也就完成了dubbo-bd解析器的注册(何为dubbo-bd解析器的注册呢?就是将dubbo自定义的标签和dubbo的bd解析器做映射存到一个map里,这就是init()方法的全部操作),执行玩init()方法后就会返回Namespace的处理器。
dubbo原理之标签解析
接着DubboBeanDefinitionParser执行parse()方法(里面主要就是一些解析标签赋值给XXXConfig类的操作),最后返回BeanDefinition。至此解析自定义的标签有关dubbo的解析结束,里面涉及到了服务的暴露的整个过程,以及将标签属性值赋值绑定到XXXConfig类上的操作,返回BeanDefinition,后续就是一些spring的其他动作如下图:
dubbo原理之标签解析
至此,服务提供者的容器启动成功。。。。。

dubbo原理之标签解析结束。。。。