1、序言
基于注解集成方式,分析Spring是如何加载Dubbo提供者相关配置
2、环境准备
clone dubbo 2.7.7源码,运行 org.apache.dubbo.demo.provider.Application#main 方法
3、Spring加载流程
跟随上一步,可以到达此处:
1、初始化相关配置
this();
主要是初始化容器上下文的一些默认配置解析相关类(涉及到父类static代码块、static方法、构造器等初始化顺序相关问题,该问题大多出现在笔试中)
2、注册配置类
将 ProviderConfiguration 封装成 AnnotatedGenericBeanDefinition,并注册到Spring容器中保存
// 方法路径
--> register(annotatedClasses);
--> org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>, java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>...)
--> org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
--> org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
将 ConfigurationClassPostProcessor 注册到容器中, BeanName 为 org.springframework.context.annotation.internalConfigurationAnnotationProcessor
部分逻辑如下所示:
3、容器刷新
refresh();
该逻辑也是Spring启动的核心逻辑,主要操作如下图所示:
invokeBeanFactoryPostProcessors(beanFactory)
大致主要逻辑如下:
/**
*
* 执行 BeanDefinitionRegistryPostProcessor
*
* 1、先处理实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor
* 2、再处理实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor
* 3、最后处理未实现以上两种接口的其它的 BeanDefinitionRegistryPostProcessors
*
* 执行 BeanFactoryPostProcessor,获取到所有该实现类的 Bean, 按 PriorityOrdered、Ordered、其它类型做分组
*
* 1、先处理实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor
* 2、再处理实现了 Ordered 接口的 BeanFactoryPostProcessor
* 3、最后处理未实现以上两种接口的其它的 BeanFactoryPostProcessor
*
*/
处理 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor :
其中,在 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法中,根据BeanDefinitionRegistryPostProcessor 类型获取 beanName, 根据一系列条件过滤后,结果为: org.springframework.context.annotation.internalConfigurationAnnotationProcessor,对应的 bean 为: ConfigurationClassPostProcessor (在步骤2中【注册配置类】注入)
获取 beanName 过滤逻辑:
执行 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry) , 跟随源码进入此处:
processConfigBeanDefinitions(registry) :真正的意义是: 解析带 @Configuration 注解的配置类
该方法主要做了以下几件事:
1、过滤出带 @Configuration 注解的 BeanDefinitionHolder
2、按 @Order 注解定义的值进行降序排序
3、递归解析每一个带 @Configuration 注解的类,并生成 BeanDefinition 信息
4、解析 @ImportRegistry 注解类并生成 BeanDefinition
主要看步骤3,解析 @Configuration 配置类逻辑:
parser.parse(candidates) : 解析配置类,并生成 BeanDefinition 信息注册到容器中
-> parser.parse(candidates);
-> ConfigurationClassParser#parse(java.util.Set)
-> #parse(AnnotationMetadata, java.lang.String)
-> #processConfigurationClass
-> #doProcessConfigurationClass
-> #processImports
this.reader.loadBeanDefinitions(configClasses) : 加载配置类生成的 BeanDefinition 信息
-> this.reader.loadBeanDefinitions(configClasses)
-> ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
-> #loadBeanDefinitionsFromRegistrars
DubboConfigConfigurationRegistrar 注册 BeanDefinition :
主要做了三件事:
1、注册 DubboConfigConfiguration.Single.class 的 BeanDefinition 信息
2、根据 @EnableDubboConfig 配置属性 multiple 决定是否注册 DubboConfigConfiguration.Multiple.class 的 BeanDefinition 信息
3、注册 Dubbo 公用的 BeanDefinition 信息 (包含 3个Bean后置处理器,2个事件监听 )
registerBeanPostProcessors(beanFactory)
获取所有 类型为 BeanPostProcessor 的 bean,并且按 实现 @PriorityOrdered、@Ordered、其它类型依次注册
initApplicationEventMulticaster()
初始化事件多播器并注册到容器中,发布事件使用
finishBeanFactoryInitialization(beanFactory)
将容器中存储的 BeanDefinition 信息,转换为 Bean 并注册到容器中 ;(该解析流程中还涉及到Spring常问的高频题:Spring 循环依赖)
finishRefresh()
完成容器启动,发布事件,Dubbo 由两个监听器进行监听: DubboLifecycleComponentApplicationListener、DubboBootstrapApplicationListener
-> finishRefresh()
-> AbstractApplicationContext#publishEvent(ApplicationEvent)
-> #publishEvent(java.lang.Object, org.springframework.core.ResolvableType)
-> SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent,ResolvableType)
-> #invokeListener
-> #doInvokeListener
-> DubboLifecycleComponentApplicationListener#onApplicationContextEvent
-> #onContextRefreshedEvent
-> DubboBootstrapApplicationListener#onApplicationContextEvent
-> #onContextRefreshedEvent
-> org.apache.dubbo.config.bootstrap.DubboBootstrap#start
DubboLifecycleComponentApplicationListener : 初始化Dubbo生命周期相关流程
DubboBootstrapApplicationListener: Dubbo 引导类,主要执行 Provider 服务暴露 相关流程
总结
- 该篇文章简要讲解了Dubbo提供者服务暴露过程是如何跟Spring进行集成的
- 通过写此篇文章,简要重新复习了一遍Spring的加载过程
- 通过Dubbo跟Spring的集成,其它框架融入Spring生命周期的模式应该类似
- 可以借鉴上述经验,写一些自定义的插件