服务暴露 之 Dubbo与Spring集成

743 阅读3分钟

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 由两个监听器进行监听: DubboLifecycleComponentApplicationListenerDubboBootstrapApplicationListener

-> 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生命周期的模式应该类似
  • 可以借鉴上述经验,写一些自定义的插件