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:如果启动过程中抛出异常,会触发此事件,可用于日志记录、通知、资源清理。