SpringBoot-SpringBoot项目启动流程分析
参考文献
启动流程
- 基于
SpringBoot 2.7.x
构造函数
1 | public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { |
run
1 | /** |
- 第一步: 获取并启动监听器
- 第二步: 根据
SpringApplicationRunListeners
以及参数来准备环境 - 第三步: 创建
Spring
容器(创建应用上下文),一般web应用,最终会执行new AnnotationConfigServletWebServerApplicationContext()
来创建上下文 - 第四步:
Spring
容器前置处理(准备上下文,主要对上一步创建好的上下文进行配置、完善,这一步会加载所有的bean
定义) - 第五步: 刷新容器(刷新上下文,主要调用高级容器的refresh()刷新上下文,这一步会实例化所有的单例
bean
,懒加载的除外) - 第六步:
Spring
容器后置处理(执行刷新后处理,这个方法是protected
修饰的空方法,作为预留的扩展点可被子类重写,可以在上下文刷新之后做一些自定义的操作) - 第七步: 发出结束执行的事件(运行监听器的started()回调方法)
- 第八步: 执行
Runners
(执行Runner
回调,这也是一个扩展点,可以在应用启动后,根据main()参数做一些自定义的处理)
获取运行监听器
1 | private SpringApplicationRunListeners getRunListeners(String[] args) { |
SpringApplicationRunListener
1 | public interface SpringApplicationRunListener { |
- 在Spring中具体的实现为
org.springframework.boot.context.event.EventPublishingRunListener
EventPublishingRunListener
中包含一个SimpleApplicationEventMulticaster
事件广播器,广播器中包含多个ApplicationListener
事件监听器
监听方法 | 运行阶段说明 | SpringBoot事件 |
---|---|---|
starting() |
Spring 应用刚启动 |
ApplicationStartingEvent |
environmentPrepared(ConfigurableEnvironment environment) |
ConfigurationEnvironment 准备妥当,允许将其调整 |
ApplicationEnvironmentPreparedEvent |
contextPrepared(ConfigurableApplicationContext context) |
ConfigurableApplicationContext 准备妥当,运行将其调整 |
ApplicationContextInitializedEvent |
contextLoaded(ConfigurableApplicationContext context) |
ConfigurableApplicationContext 已装载,但仍未启动 |
ApplicationPreparedEvent |
started(ConfigurableApplicationContext context) |
ConfigurableApplicationContext 已启动,此时Spring Bean 已初始化完成 |
ApplicationStartedEvent |
running(ConfigurableApplicationContext context) |
Spring 应用正在运行 |
ApplicationReadyEvent |
failed(ConfigurableApplicationContext context, Throwable exception) |
Spring 应用运行失败 |
ApplicationFailedEvent |
ApplicationListener
和SpringApplicationRunListener
的区别
-
它们的主要区别在于它们监听的时间点和处理的事件类型不同.
-
ApplicationListener
-
ApplicationListener
是Spring框架中的通用事件监听器接口,用于监听Spring应用程序中的各种事件,如上下文刷新事件、上下文关闭事件、Web请求处理事件等.它可以监听所有Spring事件,而不仅仅是Spring Boot事件. -
ApplicationListener
的实现类需要实现onApplicationEvent()
方法,该方法在监听到事件时被调用.例如,下面的代码演示了如何实现一个ApplicationListener
,以监听上下文刷新事件:1
2
3
4
5
6
7
8
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
// 处理上下文刷新事件
}
}
-
-
SpringApplicationRunListener
-
SpringApplicationRunListener
是Spring Boot中的特定类型的监听器,它用于监听Spring Boot应用程序的生命周期事件,如应用程序启动事件、应用程序关闭事件等 -
需要注意的是,
SpringApplicationRunListener
的实现类需要在META-INF/spring.factories
文件中进行声明,例如:1
2org.springframework.boot.SpringApplicationRunListener=\
com.example.MyRunListener
-
根据SpringApplicationRunListeners
以及参数来准备环境
1 | private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, |
1 | private ConfigurableEnvironment getOrCreateEnvironment() { |
1 | protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) { |
1 | protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) { |
创建Spring应用上下文
- 通过Web的类型判断执行
ApplicationContextFactory
的create
方法 - 具体为
AnnotationConfigReactiveWebServerApplicationContext
和AnnotationConfigServletWebServerApplicationContext
1 | protected ConfigurableApplicationContext createApplicationContext() { |
1 |
|
1 | /** |
1 | /** |
- 以常用的
AnnotationConfigServletWebServerApplicationContext
为例
1 | public AnnotationConfigServletWebServerApplicationContext() { |
org.springframework.context.annotation.AnnotatedBeanDefinitionReader
1 | /** |
org.springframework.context.annotation.ClassPathBeanDefinitionScanner
1 | /** |
Spring上下文前置处理
1 | private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, |
刷新上下文
1 | private void refreshContext(ConfigurableApplicationContext context) { |
1 | /** |
1 | // org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh |
-
org.springframework.context.support.AbstractApplicationContext#refresh
分析,参考Spring源码-分析(Spring5.1.x) -
其中
onRefresh()
由ServletWebServerApplicationContext
来实现
1 | //org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh |
1 | private void createWebServer() { |
Spring上下文后置处理
- 这是一个模板方法设计模式,默认是空的实现,是SpringBoot的一个扩展接口,可以重写该方法自定义一些需求,比如打印一些启动结束log,或者其他的后置处理.
1 | /** |
发出结束执行的事件
1 | void started(ConfigurableApplicationContext context, Duration timeTaken) { |
1 | default void started(ConfigurableApplicationContext context, Duration timeTaken) { |
1 | // org.springframework.boot.context.event.EventPublishingRunListener#started |
执行Runners
1 | private void callRunners(ApplicationContext context, ApplicationArguments args) { |
SpringApplication
调整应用行为
SpringApplication
调整应用行为的方法都与SpringApplicationBuilder
方法一一对应
SpringApplication方法 | SpringApplicationBuilder方法 | 场景说明 | 默认值 | 起始版本 |
---|---|---|---|---|
setAddCommandLineProperties |
addCommandLineProperties |
是否添加命令行参数 | true | 1.0 |
setAdditionalProfiles |
additionalProfiles |
添加SpringProfile | 空Set | 1.0 |
setBanner |
banner |
设置Banner实现 | null | 1.2 |
setBannerMode |
bannerMode |
设置Banner.Mode,包括日志(LOG),控制台(CONSOLE)和关闭 | CONSOLE | 1.3 |
setBeanNameGenerator |
beanNameGenerator |
设置@Configuration Bean名称的生成器实现 | null | 1.0 |
setDefaultProperties |
properties |
多个重载方法,配置默认的配置项 | null | 1.0 |
setEnvironment |
environment |
关联当前应用的Environment实现类 | null | 1.0 |
setInitializers |
/ |
覆盖更新ApplicationContextInitializer集合 | 所有META-INF/spring.factories资源中声明的ApplicationContextInitializer集合 | 1.0 |
addInitializers |
initializers |
追加ApplicationContextInitializer集合 | 同上 | 1.0 |
setListeners |
/ |
覆盖更新ApplicationListener | 所有META-INF/spring.factories资源中声明的ApplicationListener集合 | 1.0 |
addListeners |
initializers |
追加ApplicationListener集合 | 同上 | 1.0 |
setLogStartupInfo |
logStartupInfo |
是否日志输出启动时信息 | true | 1.0 |
setMainApplicationClass |
main |
设置Main Class,主要用于调整日志输出 | 由deduceMainApplicationClass()方法推断 | 1.0 |
setRegisterShutdownHook |
registerShutdownHook |
设置是否让ApplicationContext注册ShutdownHook线程 | true | 1.0 |
setSources |
sources |
增加SpringApplication配资源 | 空Set | 1.0 |
setWebApplicationType |
web |
设置WebApplicationType | 由deduceMainApplicationClass()方法推断 | 2.0 |
addPrimarySources |
/ |
添加主配置类 | 有SpringApplication构造参数决定 | 2.0 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!