图解:SpringBoot Spring Dubbo 启动过程
OverView
Java程序员都应清楚Spring生命周期,这是Java程序员的基础知识。牢牢掌握这些知识点这不仅仅可以应付面试,更重要的是,可以更好的分析实际工作中的问题。
本文将把SpringBoot、Spring、Dubbo结合起来,分析他们的启动流程。整个过程大致会长下面这个样子。
下面,我们就分别看看SpringBoot
的启动过程。
SpringBoot的启动过程
SpringBoot
可以理解为Spring的启动程序,启动程序的入口方法为SpringApplication.run()
,详细如下:
A: 通知 Listener,start
B: 创建Enviroment
,Enviroment
是整个应用的配置以及Profile
的承载类
C: 创建容器
D: 初始化容器, ApplicationContext.refresh()
即为容器初始化入口
E: 空方法
F: 通知 Listener,started
G: 通知 Listener,running
通过观察发现:SpringBoot.run()
中代码步骤,大致可以归纳总结为两种行为动作:
SpringApplicationRunListeners
调用(蓝色)- 创建和初始化容器(绿色)两部分
所以个人觉得SpringApplicationRunListeners
代表了SpringBoot
的生命周期,这个生命周期描述了SpringBoot的启动过程,如:创建初始化Enviroment
,创建初始化容器
总结:SpringBoot的生命周期,如下图:
Spring启动过程
在SpringBoot启动过程中,会创建、刷新ApplicationContext
。结合上面的流程后,如下图:
这里的refreshContext
,就是Spring容器创建初始化的过程,下面我们详细介绍一下此过程。
Spring中有一个类AbstractApplicationContext
,所有类型的ApplicationContext,例如ClassPathXmlApplicationContext
,FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
都是继承此类。
AbstractApplicationContext 中有一个著名的方法refresh(),Spring容器的设计者们将容器启动过程抽象到了这个方法中,也就是AbstractApplication.refresh()
方法中。 所有类型的ApplicationContext都会进入此方法。
Dubbo的启动过程
Dubbo程序是以Spring Beans的形式存在于Spring容器中,随着Spring容器启动而启动。
对于Dubbo业务方来说,主要有两个重要的Bean,ServiceBean
和ReferenceBean
,他们各自会调用Service.export()和Reference.get()来暴露服务以及引用远程服务。
在使用这两个Bean的时候,Dubbo的设计者为了让用户可以以Annotation的方式方便的使用,他们利用Spring的众多扩展点,在Spring容器启动过程中,自动发现、注册、实例化了ServiceBean
与ReferenceBean
。
具体流程图如下:
BeanDefinition的注册
EnableDubbo:
如果我们是使用Annotation方式使用Dubbo,那么会在SpringConfig类中添加@EnableDubbo
注解,这个注解会利用@Import
注解的BeanDefinition注册机制,向容器中注册DubboConfigBindingBeanPostProcessor
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcesser
这三个重要的postProcessor来完成ServiceBean
与ReferenceBean
的创建。
@Import注解是由下面的ConfigurationClassPostProcessor
读取执行的。
ConfigurationClassPostProcessor:
Spring在容器的refresh()方法执行过程中,当BeanFactory准备好后就会执行invokeBeanFactoryPostProcessors(BeanFactory)
,如果debug源码会发现刚开始候容器只有ConfigurationClassPostProcessor
这一个BeanFactoryPostProcessor,它的作用,按照源码的说法是:Bootstrapping processing of @Configuration 。源码注解大概意思是:它是第一个加载进容器并被执行的BeanFactoryPostProcessor
,然后他作为Configuration引导过程,自动导入程序中的其他Configuration相关类。
原来,@Configuration @Import就是由它读取执行的。
ServiceAnnotationBeanPostProcessor:
时机:
ServiceAnnotationBeanPostProcessor
是一个BeanFactoryPostProcessor在容器invokeBeanFactoryPostProcessors()过程中,会被执行。
作用:以@Service
作为过滤条件,扫描指定scanBasePackages
,向容器注册ServiceBean。在refresh完成的时候,会向容器中发送ContextRefershEvent
,ServiceBean实例会监听此事件,然后执行服务export过程。
扩展点:BeanFactoryPostProcessor
Bean初始化
ReferenceAnnotationBeanPostProcessor:
时机:
- 在容器初始化完成后,会实例化容器中的单例非懒初始化Bean。
- 在实例化Bean以后,初始化Bean属性前会调用populateBean()方法,执行
AnnotationInjectedBeanPostProcessor
为注入依赖的属性。 - 而
ReferenceAnnotationBeanPostProcessor
就是继承自AnnotationInjectedBeanPostProcessor
,此时它会随着一起执行。
动作:
- 加载扫描目录
scanBasePackages
下的类,找到@Reference
所注解的字段,为其注入值。 - 注入的值为业务接口的动态代理类,动态代理(InvocationHandler)的逻辑是调用
ReferenceBean.get()
方法,创建真正的Invoker
。 - 所以最终注入了封装了远程调用逻辑的
Invoker
Sping扩展点:BeanPostProcessor
AnnotationInjectedBeanPostProcessor
DubboConfigBindingBeanPostProcessor:
作用:为配置承载类:ApplicationConfig
ModuleConfig
RegistryConfig
ProtocolConfig
等自动状态配置
Spring扩展点:BeanPostProcessor
posted on 2020-01-30 18:06 yipianlarou 阅读(2740) 评论(0) 编辑 收藏 举报