一、Dubbo整合Spring启动流程
Dubbo的使用可以不依赖Spring,但是生产环境中Dubbo都是整合到Spring中一起使用,所以本章就解析Dubbo整合Spring的启动流程
一、传统的xml解析方式
一、Dubbo配置解析流程
在Java 中,一切皆对象。在JDK 中使用java.lang.Class 来描述类这个对象。而在Spring 中,bean 对象是操作核心。那么Spring 也需要一个东西来描述bean 这个对象,它就是BeanDefinition。
dubbo 的配置解析,不论是xml 方式的配置,还是注解的配置,目标都是把配置的属性值提取出来,变成dubbo 的组件bean(先由BeanDefinition 描述,然后委托spring 生成组件bean)。
下面以xml 的标签为例,列出每种配置对应要解析成为的目标组件bean。
首先,dubbo 自定义了spring 标签描述dubbo.xsd。在dubbo-config-spring模块下的src/main/resouce/META-INF 下,其次,在spring.handlers、spring.schemas 中指定解析类,将标签引入spring 中管理。
来到DubboNamespaceHandler中的init()方法,引入了很多DubboBeanDefinitionParser类,每个类会解析对应的配置,DubboBeanDefinitionParser 继承了spring 的BeanDefinitionParser 接口,spring 会调用parse 方法来读取每个标签配置,将属性值装入对应的BeanDefinition 定义中,后续spring会根据此BeanDefinition 定义生成dubbo 的组件bean。
继续看下DubboNamespaceHandler中的parse()方法,spring启动过程中同样会调用到这个方法,方法中有一行DubboSpringInitializer.initialize(parserContext.getRegistry())方法,就是向容器中加入一些基础bean。
我们先看两个比较重要的也就是ReferenceAnnotationBeanPostProcessor,DubboDeployApplicationListener;其中ReferenceAnnotationBeanPostProcessor是处理@Reference注解的,而DubboDeployApplicationListener是DubboDeployApplicationListener会监听Spring容器启动完成事件ContextRefreshedEvent,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出与服务引入。
到此,那么dubbo中的一些必要的基本类已经假如到容器中了,也就是已经具备了解析处理dubbo.xml的基本条件。
二、Service标签处理
看下解析service标签的DubboBeanDefinitionParser,spring启动过程中会执行到parse方法,最终将service对应的Class信息设置到beanDefinition中,并且调用registerBeanDefinition方法将该beanDefinition注册到BeanDefinition中。
注意到此时的beanClass为ServiceBean,该类实现了InitializingBean接口,那么最终实例化的时候会调用afterPropertiesSet方法,这里会将ServiceBean加入到dubbo的configsCache缓存中,后面进行服务暴漏的时候就是从这个缓存中获取的。
三、Reference标签处理
同理reference标签的处理跟service标签一样,同样会通过DubboBeanDefinitionParser将他的class信息设置到beanDefinition中,此时class信息为referenceBean。这个接口实现了FactoryBean接口,那么最终spring会调用他的getObject方法,可以看到该方法里面去创建代理对象lazyProxy对象。
referenceBean同时也实现了InitializingBean,最终也会调用到afterPropertiesSet()方法,这里会将referenceBean添加到缓存中。
四、DubboDeployApplicationListener
当Spring容器启动完成会发布事件ContextRefreshedEvent,DubboDeployApplicationListener会监听这个事件,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出(服务暴漏)与服务引用。
还记得serviceBean初始化的时候执行的afterPropertiesSet方法吗,会将ServiceBean加入到dubbo的configsCache缓存中,这里会取出来挨个进行服务导出。
同时也会从configManager中获取references进行服务的引用,也就是生成具体的远程调用代理类,最终会调用到referenceConfig中的init方法,ref就是生成的代理对象,也就是实际的业务执行者。
二、注解方式
一、@EnableDubbo
服务端代码如下:需要在配置类上加上@EnableDubbo注解
@EnableDubbo注解上面有一个注解@DubboComponentScan,点进去这个注解发现他引入了这个DubboComponentScanRegistrar,该类实现了ImportBeanDefinitionRegistrar,spring启动过成功会调用registerBeanDefinitions方法
这里有三个比较关键的方法:
1、DubboSpringInitializer.initialize(registry);
这一步在xml解析的过程中已经解释过,引入了ReferenceAnnotationBeanPostProcessor,DubboDeployApplicationListener两个核心类;
2、Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
这一步是获取@DubboComponentScan上面的包路径,并传递给ServiceAnnotationPostProcessor,这个类会去扫描这个包下的带有@DubboService注解的类
3、将ServiceAnnotationPostProcessor注入到spring容器中,后续进行@DubboService注解解析
二、ServiceAnnotationPostProcessor
这个类实现了BeanDefinitionRegistryPostProcessor,最终Spring会调用到postProcessBeanDefinitionRegistry方法中,而scanServiceBeans方法就是将包路径下带有@DubboService的类解析为beanDefinition然后加入到spring容器中。
最终还是会通过serviceBean的afterPropertiesSet方法将ServiceBean加入到dubbo的configsCache缓存中,后面进行服务暴漏的时候就是从这个缓存中获取的
三、ReferenceAnnotationBeanPostProcessor
spring执行过程中会调用postProcessMergedBeanDefinition方法收集类中带有@DubboReference注解的属性,并最终调用postProcessPropertyValues将类上的属性注入到类中。
referenceBean也实现了InitializingBean,最终也会调用到afterPropertiesSet()方法,这里会将
referenceBean添加到缓存中。
四、DubboDeployApplicationListener
当Spring容器启动完成会发布事件ContextRefreshedEvent,DubboDeployApplicationListener会监听这个事件,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出(服务暴漏)与服务引入。
还记得serviceBean初始化的时候执行的afterPropertiesSet方法吗,会将ServiceBean加入到dubbo的configsCache缓存中,这里会取出来挨个进行服务导出。
在这里会从configManager中获取references进行服务的引用,也就是生成具体的远程调用代理类,最终会调用到referenceConfig中的init方法,ref就是生成的代理对象,也就是实际的业务执行者。
三、服务调用
当进行服务调用的时候此时的demoService其实就是ReferenceBean.getObject()方法返回的lazyProxy对象,执行方法调用时会通过createObject然后getCallProxy获取到执行业务的对象。
最终会来到referenceConfig.get()方法,由于ref属性已经在dubbo启动的时候通过referServices初始化完成,所以这里已经不是null了,最终调用该ref执行业务逻辑的调用。
至此、Dubbo整合spring的大致启动流程结束,下个章节解析Dubbo的服务暴漏与注册。