SpringBoot 启动流程

Spring Boot 的启动过程进过初始化 (Initialization)、准备 (Preparation) 和运行 (Running)。这三个阶段通过事件机制向外暴露了大量可扩展点。

第一阶段:应用初始化(SpringApplication 构建与准备)

当你在 main 方法中调用 SpringApplication.run(MyApp.class, args) 时,Spring Boot 首先会创建一个 SpringApplication 对象。在这个过程中,它会完成以下核心工作:

1.1. 创建 SpringApplication 实例

在 run 方法内部,首先通过 new SpringApplication(primarySources) 创建实例。此过程会完成:

  • 推断应用类型:通过 WebApplicationType.deduceFromClasspath() 判断是 SERVLET(传统 Web)、REACTIVE(响应式 Web)还是 NONE(普通应用)。

1.2. 加载 SPI 扩展

加载 SPI 扩展,通过 SpringFactoriesLoader 从所有 META-INF/spring.factories 文件中加载组件,并实例化。

  • 加载 ApplicationContextInitializer:在容器刷新前执行预处理
  • 加载 ApplicationListener:用于监听应用启动过程中的事件。

可扩展点:

  • SpringApplicationRunListener:虽然此时未触发回调,可以通过在 META-INF/spring.factories 中定义,或用 SpringApplication.addInitializers() 等方式添加自定义的 ApplicationContextInitializer配置自定义实现,覆盖整个启动流程的监听(本阶段暂无回调)。

1.3.定位启动主类:

通过遍历调用栈,找到包含 main 方法的类。

第二阶段:准备 (Preparation) ------ 为容器启动铺垫

完成初始化后,run 方法会进入准备阶段,该阶段通过事件监听器逐步构建运行环境,并发布一系列关键事件。

2.1. 触发事件:ApplicationStartingEvent

这是最早触发的事件,可在此做启动前置操作(如检查 Java 版本、设置系统属性)。

  • 对应回调:SpringApplicationRunListener.starting()

可扩展点:

  • 实现 SpringApplicationRunListener 接口,并配置在 spring.factories 中。

2.2. 准备环境(prepareEnvironment)

创建并配置 ConfigurableEnvironment,按优先级加载 application.properties、命令行参数等配置源。

  • 触发事件:ApplicationEnvironmentPreparedEvent
  • 对应回调:SpringApplicationRunListener.environmentPrepared(ConfigurableEnvironment)

可扩展点:

  • 监听 ApplicationEnvironmentPreparedEvent:可在环境准备完成后,动态修改或添加配置(如从远程配置中心拉取配置后覆盖)。
    EnvironmentPostProcessor:这是专门用于在 Environment 准备完成后,额外添加配置源的扩展点(例如引入自定义配置文件)。需在 spring.factories 中声明。

2.3. 创建与准备应用上下文(createApplicationContext & prepareContext)

创建上下文:

  • 根据步骤 1 推断的应用类型,实例化对应的 ApplicationContext(如 AnnotationConfigServletWebServerApplicationContext)。

准备上下文:

  • 将 Environment 注入上下文。
  • 执行所有 ApplicationContextInitializer 的 initialize 方法。
  • 将 BeanNameGenerator 和 ResourceLoader 等组件设置到上下文。
  • 加载启动类上的 @SpringBootApplication 等配置源(通过 load 方法)。

触发事件:

  • ApplicationContextInitializedEvent(在所有 Initializer 执行完成后触发)
  • ApplicationPreparedEvent(在上下文加载完成后触发)
  • 对应回调:SpringApplicationRunListener.contextPrepared() 和 SpringApplicationRunListener.contextLoaded()

可扩展点:

  • ApplicationContextInitializer.initialize():这是修改容器的最后机会。例如,可以在此设置 Profiles、添加 -BeanFactoryPostProcessor 或注册额外的 Bean 定义。
  • 监听 ApplicationContextInitializedEvent 和 ApplicationPreparedEvent。

第三阶段:运行阶段

这是启动的核心阶段,ApplicationContext 被"刷新",所有 Bean 的生命周期都在此完成,内嵌的 Web 服务器启动,应用最终准备就绪。

3.1. 容器刷新(refresh 核心流程)

3.1.1 refresh 前置准备(prepareRefresh)

设置上下文状态为"激活中",校验配置文件中的必需属性,初始化早期事件监听器。

可扩展点:几乎无业务扩展点,属于框架内部准备。

3.1.2 获取 BeanFactory(obtainFreshBeanFactory)

销毁已有的 BeanFactory(如有),创建新的 DefaultListableBeanFactory 实例,并加载所有 Bean 定义(BeanDefinition)。此时,BeanDefinition 已全部解析完成。

可扩展点:此时尚未提供用户扩展入口,但 BeanDefinition 已经就绪。

3.1.3 BeanFactory 前置准备(prepareBeanFactory)

设置 ClassLoader、BeanExpressionResolver。

添加 BeanPostProcessor:ApplicationContextAwareProcessor(用于处理 Aware 回调)。

忽略特定的依赖接口(如 EnvironmentAware、ResourceLoaderAware 等,因为容器会自动注入)。

注册特殊的 Bean:ApplicationContext、Environment、ResourceLoader 等。

可扩展点:无直接用户扩展点,但可通过 ApplicationContextInitializer 在此前介入。

3.1.4 BeanFactory 后置处理(postProcessBeanFactory)

允许子类(如 AnnotationConfigServletWebServerApplicationContext)在 BeanFactory 准备完成后,添加额外的 BeanPostProcessor 或忽略特定接口。

可扩展点:

  • 重写 postProcessBeanFactory 方法(通常不推荐)。

3.1.5 执行 BeanFactory 后置处理器(invokeBeanFactoryPostProcessors)

这是修改 BeanDefinition 的核心扩展点入口,严格按优先级执行:

调用所有实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor。

调用所有实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor。

调用其余的 BeanDefinitionRegistryPostProcessor。

类似地,再调用所有 BeanFactoryPostProcessor(先 PriorityOrdered,再 Ordered,最后普通)。

可扩展点:

  • BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry():可在此动态注册新的 Bean 定义、移除已有的 Bean 定义或修改其作用域、懒加载标志等。
  • BeanFactoryPostProcessor.postProcessBeanFactory():可在此修改已加载的 Bean 定义属性(如修改 @Value 的值、更改作用域),但不能注册新的 Bean 定义。

3.1.6 注册 BeanPostProcessor(registerBeanPostProcessors)

将项目及框架中所有实现了 BeanPostProcessor 接口的 Bean 注册到 BeanFactory(注意:此时仅实例化和注册,不执行其钩子方法,执行要等到 Bean 实例化时)。

可扩展点:

  • 将自定义的 BeanPostProcessor 定义为普通 Bean(添加 @Component)即可被自动注册。

3.1.7 初始化消息源(initMessageSource)

初始化国际化相关的 MessageSource Bean。

可扩展点:

  • 如果需要自定义国际化实现,可定义自己的 MessageSource Bean。

3.1.8 初始化应用事件广播器(initApplicationEventMulticaster)

创建 ApplicationEventMulticaster,用于后续的事件广播。

可扩展点:

  • 可定义自定义的 ApplicationEventMulticaster Bean 覆盖默认实现。

3.1.9 刷新上下文时的特殊处理(onRefresh

这是极其关键的一步。对于 Web 应用(ServletWebServerApplicationContext),会在此方法中调用 createWebServer(),从而启动内嵌的 Tomcat、Jetty 或 Undertow 服务器。

此时会初始化 ServletWebServerFactory(如 TomcatServletWebServerFactory),绑定端口,并启动服务器。

然而,此时 DispatcherServlet 尚未初始化,因此虽然 Tomcat 已经可以接收请求,但请求会被阻塞或返回 404,直到后续步骤完成。

可扩展点:

  • WebServerFactoryCustomizer:在 spring.factories 中定义或定义为 Bean,用于定制 Web 服务器(如修改端口、设置 SSL、调整线程池参数)。
  • ServletContextInitializer:用于编程式地配置 ServletContext(如注册 Servlet、Filter、Listener)。

3.1.10 注册监听器(registerListeners)

将实现了 ApplicationListener 接口的 Bean 注册到事件广播器,并广播早期事件(步骤 5 中积累的事件)。

可扩展点:

  • 无特殊扩展点,但请注意所有 ApplicationListener 在此步骤被注册。

3.1.11 完成 BeanFactory 初始化(finishBeanFactoryInitialization)

这是所有业务 Bean 被实例化、依赖注入、初始化的核心环节。

实例化所有非懒加载的单例 Bean(包括 @Component、@Service、@Controller 等)。

每个 Bean 实例化的完整生命周期顺序如下:

  • 实例化:调用构造方法(new),分配内存。
  • 依赖注入:通过 @Autowired、@Value 等填充属性。
  • Aware 接口回调:如 BeanNameAware、BeanFactoryAware、ApplicationContextAware。
  • BeanPostProcessor.postProcessBeforeInitialization()。
  • 初始化回调:@PostConstruct → InitializingBean.afterPropertiesSet() → 自定义 init-method。
  • BeanPostProcessor.postProcessAfterInitialization()(AOP 代理在此生成)。

可扩展点:

  • BeanPostProcessor:所有在步骤 10 中注册的 BeanPostProcessor 将在此阶段依次作用于每个 Bean 的实例化前后,是实现 AOP、代理、属性注入拦截的核心。
  • InitializingBean / @PostConstruct / init-method:用于 Bean 自身初始化逻辑。
  • Aware 接口:用于获取 Spring 底层组件(如 ApplicationContext)。

3.1.12 完成刷新(finishRefresh)

清理资源缓存(如 ReflectionUtils 的缓存)。

初始化 LifecycleProcessor:查找或创建默认的 LifecycleProcessor。

调用 LifecycleProcessor.onRefresh(),启动所有实现了 SmartLifecycle 接口且 isAutoStartup() 返回 true 的 Bean 的 start() 方法(例如消息监听容器)。

发布 ContextRefreshedEvent:标志着 ApplicationContext 已完成刷新,所有 Bean 准备就绪。

可扩展点:

  • SmartLifecycle / Lifecycle 接口:实现此接口的 Bean 可在此阶段被自动启动,适用于需要显式 start/stop 的资源(如 MQ 消费者、定时任务)。
  • 监听 ContextRefreshedEvent:可在此执行容器完全加载后的全局初始化逻辑(但注意,ApplicationRunner 和 CommandLineRunner 尚未执行)。

3.2. 刷新后处理(afterRefresh)

refresh() 方法执行完毕,回到 SpringApplication.run() 的收尾流程。

空方法,预留扩展。

可扩展点:极少使用。

3.2.1 发布启动事件并执行 Runner(start & running)

触发事件:ApplicationStartedEvent

对应回调:SpringApplicationRunListener.started(ConfigurableApplicationContext)

执行 ApplicationRunner 和 CommandLineRunner:所有实现了这两个接口的 Bean 的 run 方法在此被执行。

触发事件:ApplicationReadyEvent

对应回调:SpringApplicationRunListener.running(ConfigurableApplicationContext)

可扩展点:

  • ApplicationRunner / CommandLineRunner:应用启动后的业务初始化操作(如预热缓存、加载字典数据)。两者区别在于参数解析方式。
  • 监听 ApplicationStartedEvent 和 ApplicationReadyEvent:前者在 Runner 执行前,后者在 Runner 执行后。
    ApplicationListener:如果启动过程中抛出异常,会触发此事件,可用于日志记录、通知、资源清理。
相关推荐
吴声子夜歌1 小时前
SQL进阶——EXISTS谓词
java·数据库·sql
偏爱自由 !1 小时前
8. 泛型程序设计
java·开发语言·windows
剑挑星河月1 小时前
35.搜索插入位置
java·数据结构·算法·leetcode
海兰1 小时前
【SpringBoot 】AOP企业级权限控制方案(二)
android·java·spring boot
偏爱自由 !1 小时前
2:IDEA中git的使用--基础操作
java·git·intellij-idea
ch.ju1 小时前
Java Programming Chapter 4——Class loading
java·开发语言
LiaoWL1231 小时前
【SpringBoot合集-03】Spring Boot 启动过程学习
java·spring boot·学习
孟浩浩3 小时前
JAVA SpringAI+阿里云百炼应用开发
java·开发语言·阿里云
钱多多_qdd3 小时前
ListUtil#split和remove搭配使用的坑
java