SpringBoot应用启动过程
Spring 应用抽象
Springboot 是一个用来快速创建 Spring 应用的微服务框架,启动引导器是org.springframework.boot.SpringApplication
这个类,每个 SpringApplication
实例就表示一个 Spring 应用的启动类;Spring 应用生命周期包括创建、启动、停止。
Springboot 为 Spring 应用提供了工程创建、开发、运行环境的支持。 Spring 应用服务的抽象包含下面这些元素:
SpringApplication
用来启动一个 Spring 应用的启动引导器,启动的过程就是为 Spring 应用构建运行环境和上下文,并且自动装配应用的组件;整个过程就是 Springboot 的核心技术,也就是自动配置;ConfigurableEnvironment
Spring应用的运行环境,Spring 应用的属性参数等内容都会加载到ConfigurableEnvironment
中,为 Spring 应用组件的属性配置体统支持;ApplicationContext
Spring 应用的上下文,这是 Spring 应用运行起来后的抽象,是 Spring 应用的运行状态;Spring 应用的形态转化是从SpringApplication
转化到ApplicationContext
;SpringApplication
的主要功能就是创建、初始化、刷新ApplicationContext
;ApplicationContext
本质上是Spring 的 IOC 容器,管理 Spring 应用组件的生命周期;SpringFactoriesInstance
Spring 应用的工厂实例,就是 Spring 应用系统使用的一些组件实例,这些实例主要用于 Spring 应用以及组件的生命周期管理;这些工厂实例组件的配置一般保存在类路径下的 META-INFO 文件夹下面的 spring.factories 文件内部;该文件内部保存了这些工厂实例的实现类和接口的映射,Spring 应用通过SpringFactoriesLoader
从该文件下读取 Spring 工厂组件的实现类,并且通过反射进行实例化。ApplicationListener
Spring 应用的监听器,Spring 采取了监听器模式(观察者模式)来对应用的事件进行响应,可以实现ApplicationListener
并注册到 Spring 应用中来对 Spring 应用生命周期事件进行响应;默认的这些ApplicationListener
的实现类通过SpringFactoriesLoader
装载;ApplicationContextInitializer
Spring 使用了钩子模式(hook),定义了钩子接口,通过注册钩子,可以在 Spring 生命周期中插入钩子代码;ApplicationContextInitializer
可以在ApplicationContext
初始化时加入钩子代码,来进行一些处理;默认的这些ApplicationContextInitializer
的实现类通过SpringFactoriesLoader
装载;
SpringApplication
SpringApplication
是 Spring 应用的启动类,Springboot 通过创建 SpringApplication
实例,然后调用该实例的 run
方法来启动 Spring 应用,成功启动运行的 Spring 应用转换为 ApplicationContext
实例。下面我们看看如何启动 Spring 应用;
创建 SpringApplication
实例
SpringApplication
在创建的时候需要初始化下面的一些属性:
ResourceLoader
,设置资源加载器,用于加载 Spring 应用的配置文件,可以为 null,默认实现是DefaultResourceLoader
,也就是 Spring 应用的类路径下面加载资源文件;primarySources
,Spring 应用的启动引导类;也就是 Spring 应用的根配置;- 应用类型推断:
webApplicationType
判断 Spring Web 应用的类型,三种类型分别是:Reactive
(响应式 Web 服务器)、Servlet
(就是 SpringMVC,通过DispatcherServlet 进行请求转发)、none
表示当前应用不是 Web 应用;Spring 通过应用类型推断来确定;判断的依据就是在类路径下面扫描对应的类,如果发现org.springframework.web.servlet.DispatcherServlet
说明是基于 SpringMVC 的 web 应用,如果发现org.springframework.web.reactive.DispatcherHandler
说明是响应式 Web 应用; - 装载 Spring 工厂实例,通过
SpringFactoriesLoader
创建用于生命周期管理的监听器类、钩子类、对象工厂等; initializers
,注册 Spring 应用的上下文的初始化器列表,每一个初始化器是一个ApplicationContextInitializer
实现类,默认的实现类由SpringFactoriesLoader
装载,可以实现自定义的钩子类,并注册listeners
,注册 Spring 应用事件的监听器列表,这些应用监听器监听 Spring 应用在生命周期变化过程中产生的事件,也就是ApplicationEvent
,对这些事件进行处理;默认的实现类由SpringFactoriesLoader
装载;mainApplicationClass
,获取应用主程序的类名(main
方法所在的类)
####通过run
方法启动SpringApplication
SpringApplication
实例的run
方法用于引导和启动当前的 Spring 应用,并通过一些约定的类来完成应用启动的步骤,一般包括下面几个步骤:- 预备工作;
- 准备
ConfigurableEnvironment
; - 创建
ApplicationContext
; - 准备
ApplicationContext
; - 刷新
ApplicationContext
; - 收尾工作;
1. 预备工作
预备工作主要是注册 Spring 应用的启动监听器,就是 SpringApplicationRunListeners
,每一个监听器是SpringApplicationRunListener
实现类,默认的实现类 EventPublishingRunListener
由 SpringFactoriesLoader
装载,主要作用是每完成一个阶段,就发布相应的事件;
2. 准备 ConfigurableEnvironment
为 Spring 应用准备运行环境,这一步创建一个 ConfigurableEnvironment
实例,并将应用参数填充到 ConfigurableEnvironment
,比如被激活的 profile
值(profile
就是多环境部署时,用来区分是测试还是生产的) ;然后将 ConfigurableEnvironment
绑定到当前 Spring 应用上;这一步还会去加载 Spring 应用的配置文件(就是 application*
文件),主要过程是通过 EventPublishingRunListener
发布 ApplicationEnvironmentPreparedEvent
事件,通知 ConfigFileApplicationListener
处理;ConfigFileApplicationListener
读取配置文件,加载 properties
到 ConfigurableEnvironment
实例中;
3. 创建 ApplicationContext
更具应用类型创建一个合适的应用上下文实例,就是 ApplicationContext
的实现类的实例,org.springframework.context.ApplicationContext
表示 Spring 应用实例运行的上下文环境,包括应用的配置,bean 工厂,应用层级的事件发布器,资源解析器等;根据 Spring 应用的类型,会创建不同的 ApplicationContext
实例;如果应用类型是 servlet
,创建 AnnotationConfigServletWebServerApplicationContext
实例,如果是 reactive
,创建 AnnotationConfigReactiveWebServerApplicationContext
,如果是 none
,也就是非 Web 应用,创建 AnnotationConfigApplicationContext
。
4. 准备 ApplicationContext
对创建的 ApplicationContext
进行初始化,会进行下面一些工作:
- 通过注册的初始化钩子,就是
ApplicationContextInitializer
实现类进行初始化,比如ContextIdApplicationContextInitializer
会为当前的 Spring 应用分配一个 ID; - 发布
ApplicationContextInitializedEvent
事件,通知注册的ApplicationListener
来处理; - 加载 sources 组件;
- 将当前
ApplicationContext
实例注入实现了ApplicationContextAware
接口的ApplicationListener
;所以如果想获取Spring 应用的ApplicationContext
,可以注册实现了ApplicationContextAware
的ApplicationListener
; - 发布
ApplicationPreparedEvent
事件,通知ApplicationListener
来处理
#####5. 刷新ApplicationContext
Springboot 的自动化配置就是在这一步实现的,包括 spring.factories 的加载,bean 的实例化等核心工作; - 对 Spring 应用配置的属性(就是application* 文件中的键值对)进行验证;
- 刷新内部的
ConfigurableListableBeanFactory
; - 对 bean 工厂进行初始化,主要是注册一些挂钩实例,Spring IOC 容器使用了挂钩模式,在对组件生命周期管理期间,加入了钩子,就是 Bean 处理器,通过注册挂钩实例来控制
Bean
的生命周期; - 对 bean 工厂进行后置处理;
- 执行 Bean 工厂的后置处理器
invokeBeanFactoryPostProcessors
,这一步会注册一些BeanDefinitionRegistryPostProcessor
的实例,并且执行这些处理器,其中有一个实现类叫做ConfigurationClassPostProcessor
,ConfigurationClassPostProcessor
执行processConfigBeanDefinitions()
方法来对配置类进行处理;具体的思路是先获取所有的当前所有的 bean definition,并找出配置类对应的 bean definition;接着对容器进行一下转换并实例化一个ConfigurationClassParser
配置类解析器对象parser
,调用parser
的parse()
对配置类进行解析;在处理配置 bean 时,ConfigurationClassParser#doProcessConfigurationClass()
会首先迭代地处理所有嵌套的配置类,然后处理所有的@PropertySource
注解来解析属性源,再处理@ComponentScan
注解实现自动扫描,再处理@Import
注解来导入配置类,因为@SpringBootApplication
注解有@EnableAutoConfiguration
注解,而@EnableAutoConfiguration
有@Import(EnableAutoConfigurationImportSelector.class)注解;@EnableAutoConfiguration
开启了自动装配了,并导入了EnableAutoConfigurationImportSelector
组件来处理自动装配逻辑 - 注册 bean 处理器来拦截 bean 的创建;
- 初始化消息源
- 初始化
Applicaiton
的事件广播器 - 注册一些监听器
最后的工作是由 Spring IOC 容器完成