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()
中代码步骤,大体能够概括总结为两种行为动做:app
SpringApplicationRunListeners
调用(蓝色)- 建立和初始化容器(绿色)两部分
因此我的以为SpringApplicationRunListeners
表明了SpringBoot
的生命周期,这个生命周期描述了SpringBoot的启动过程,如:建立初始化Enviroment
,建立初始化容器
总结:SpringBoot的生命周期,以下图:post
Spring启动过程
在SpringBoot启动过程当中,会建立、刷新ApplicationContext
。结合上面的流程后,以下图:
这里的refreshContext
,就是Spring容器建立初始化的过程,下面咱们详细介绍一下此过程。spa
Spring中有一个类AbstractApplicationContext
,全部类型的ApplicationContext,例如ClassPathXmlApplicationContext
,FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
都是继承此类。
AbstractApplicationContext 中有一个著名的方法refresh(),Spring容器的设计者们将容器启动过程抽象到了这个方法中,也就是AbstractApplication.refresh()
方法中。 全部类型的ApplicationContext都会进入此方法。
debug
Dubbo的启动过程
Dubbo程序是以Spring Beans的形式存在于Spring容器中,随着Spring容器启动而启动。
对于Dubbo业务方来讲,主要有两个重要的Bean,ServiceBean
和ReferenceBean
,他们各自会调用Service.export()和Reference.get()来暴露服务以及引用远程服务。
在使用这两个Bean的时候,Dubbo的设计者为了让用户能够以Annotation的方式方便的使用,他们利用Spring的众多扩展点,在Spring容器启动过程当中,自动发现、注册、实例化了ServiceBean
与ReferenceBean
。设计
具体流程图以下:
3d
BeanDefinition的注册
EnableDubbo:
若是咱们是使用Annotation方式使用Dubbo,那么会在SpringConfig类中添加@EnableDubbo
注解,这个注解会利用@Import
注解的BeanDefinition注册机制,向容器中注册DubboConfigBindingBeanPostProcessor
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcesser
这三个重要的postProcessor来完成ServiceBean
与ReferenceBean
的建立。代理
@Import注解是由下面的ConfigurationClassPostProcessor
读取执行的。code
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