在Spring Boot开发中,理解应用的生命周期是实现优雅启动、资源管理与故障处理的关键。不同于传统Spring框架需要繁琐的XML配置,Spring Boot通过自动配置简化了开发流程,但其生命周期的底层逻辑仍延续并增强了Spring的核心机制。本文将从“生命周期阶段划分”“核心扩展点原理”“实操案例”三个维度,带大家彻底掌握Spring Boot的生命周期管理。
一、Spring Boot 生命周期核心阶段
Spring Boot应用的生命周期本质是“容器启动→Bean创建→应用运行→容器关闭”的完整流程,可细分为4个核心阶段,每个阶段都对应着特定的底层操作与扩展机会。
1. 启动准备阶段(Startup Preparation)
此阶段为应用启动做基础配置,核心是初始化“环境”与“监听器”,具体流程如下:
- 执行
SpringApplication.run()
方法,首先创建SpringApplication
实例; - 初始化
ApplicationContextInitializer
(应用上下文初始化器)和ApplicationListener
(应用监听器),从类路径下的META-INF/spring.factories
中加载自动配置类; - 准备
Environment
(环境对象),包含系统属性、环境变量、配置文件(application.yml/properties)等信息,并完成配置文件的解析与绑定。
关键特征:此时ApplicationContext
(应用上下文)尚未创建,仅完成基础环境搭建,适合做全局配置的预处理。
2. 容器初始化阶段(Container Initialization)
此阶段是Spring Boot的核心,负责创建ApplicationContext
(应用上下文)并初始化Bean,流程可拆解为:
- 创建
ApplicationContext
实例(如AnnotationConfigServletWebServerApplicationContext
,根据Web类型自动选择); - 调用
ApplicationContextInitializer
的initialize()
方法,对应用上下文进行预处理(如添加自定义BeanDefinition); - 注册
ApplicationListener
到应用上下文,监听后续的生命周期事件; - 加载BeanDefinition:扫描指定包下的
@Component
、@Service
等注解类,解析自动配置类(@EnableAutoConfiguration
)中的Bean; - 刷新应用上下文(
refresh()
方法):这是Spring的核心方法,包含Bean的实例化、属性注入(DI)、初始化方法执行等关键步骤。
关键特征:Bean的创建与依赖注入在此阶段完成,是扩展点最集中的阶段。
3. 应用运行阶段(Application Running)
容器初始化完成后,应用进入稳定运行阶段:
- 对于Web应用(如Spring MVC、Spring WebFlux),会启动嵌入式服务器(Tomcat、Jetty等),监听指定端口接收请求;
- 应用上下文处于“活跃”状态,Bean可正常提供服务(如处理HTTP请求、执行定时任务等);
- 此阶段可通过监听器或自定义组件监控应用状态(如健康检查、指标收集)。
关键特征:应用对外提供服务,生命周期相对稳定,扩展点主要集中在状态监控与事件响应。
4. 容器关闭阶段(Container Shutdown)
当应用收到关闭信号(如Ctrl+C
、kill命令、容器编排平台的停止指令)时,进入关闭阶段:
- 发布
ContextClosedEvent
事件,触发相关监听器的回调; - 调用单例Bean的
destroy()
方法(或@PreDestroy
注解方法),释放资源(如关闭数据库连接池、断开消息队列、销毁线程池等); - 关闭嵌入式服务器,停止接收新请求,并处理剩余的请求(优雅关闭);
- 销毁应用上下文,释放所有Bean资源。
关键特征:核心是“优雅释放资源”,避免内存泄漏或数据不一致,是保障应用稳定性的重要阶段。
二、Spring Boot 核心扩展点解析(附实操)
Spring Boot在生命周期的各个阶段提供了丰富的扩展点,允许开发者在不修改框架源码的情况下,自定义流程逻辑。以下是常用扩展点的原理与实操案例,所有案例基于Spring Boot 2.7.x版本。
1. 启动准备阶段扩展:ApplicationContextInitializer
作用
在应用上下文(ApplicationContext
)创建前,对其进行预处理(如添加自定义配置、注册BeanDefinition等),常用于框架级别的初始化。
实现步骤
- 实现
ApplicationContextInitializer
接口,重写initialize()
方法; - 注册扩展类:通过
SpringApplication.addInitializers()
或META-INF/spring.factories
配置; - 触发时机:在
ApplicationContext
创建后、刷新前执行。
实操案例:添加自定义系统属性
// 1. 实现扩展类
public class CustomContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// 往环境中添加自定义属性
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> customProps = new HashMap<>();
customProps.put("app.custom.version", "v1.0.0");
customProps.put("app.custom.env", "dev");
// 将自定义属性添加到环境中(优先级低于配置文件)
environment.getPropertySources().addLast(
new MapPropertySource("customPropertySource", customProps)
);
System.out.println("ApplicationContextInitializer:已添加自定义系统属性");
}
}
// 2. 注册扩展类(两种方式任选其一)
// 方式1:在启动类中手动注册
@SpringBootApplication
public class LifecycleDemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(LifecycleDemoApplication.class);
// 添加自定义Initializer
application.addInitializers(new CustomContextInitializer());
application.run(args);
}
}
// 方式2:通过META-INF/spring.factories配置(推荐,解耦)
// 在resources下创建META-INF/spring.factories,添加如下内容:
org.springframework.context.ApplicationContextInitializer=\
com.example.lifecycle.extension.CustomContextInitializer
验证
启动应用后,可通过@Value
注入自定义属性,或在Environment
中获取:
@RestController
public class TestController {
@Value("${app.custom.version}")
private String appVersion;
@GetMapping("/version")
public String getVersion() {
return "应用版本:" + appVersion; // 输出:应用版本:v1.0.0
}
}
2. 容器初始化阶段扩展:Bean初始化相关扩展
此阶段的扩展点主要围绕Bean的创建与初始化,常用的有@PostConstruct
、InitializingBean
、BeanPostProcessor
。
(1)@PostConstruct:Bean初始化方法注解
作用
在Bean的属性注入完成后,执行自定义初始化逻辑(如初始化缓存、加载配置),是最常用的Bean初始化方式。
原理
由JSR-250规范定义,Spring通过CommonAnnotationBeanPostProcessor
解析该注解,在Bean的afterPropertiesSet()
方法前执行。
实操案例
@Component
public class UserService {
// 模拟属性注入
@Autowired
private UserDao userDao;
// 初始化方法:在属性注入后执行
@PostConstruct
public void init() {
System.out.println("UserService:@PostConstruct初始化,加载用户缓存");
// 模拟初始化逻辑
userDao.loadCache();
}
}
(2)InitializingBean:Bean初始化接口
作用
与@PostConstruct
类似,通过实现接口方法定义Bean的初始化逻辑,优先级低于@PostConstruct
(@PostConstruct
先执行)。
实操案例
@Component
public class OrderService implements InitializingBean {
@Autowired
private OrderDao orderDao;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("OrderService:InitializingBean初始化,初始化订单队列");
// 模拟初始化逻辑
orderDao.initQueue();
}
}
执行顺序验证
若一个Bean同时使用@PostConstruct
和InitializingBean
:
@Component
public class ProductService implements InitializingBean {
@PostConstruct
public void postConstructInit() {
System.out.println("ProductService:@PostConstruct执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("ProductService:InitializingBean执行");
}
}
// 启动后输出顺序:
// ProductService:@PostConstruct执行
// ProductService:InitializingBean执行
(3)BeanPostProcessor:Bean后置处理器
作用
在所有Bean的初始化前后执行自定义逻辑,可对Bean进行增强(如AOP代理、属性修改),是Spring AOP、事务管理等功能的底层基础。
原理
postProcessBeforeInitialization()
:在Bean的初始化方法(@PostConstruct
、afterPropertiesSet()
)执行前调用;postProcessAfterInitialization()
:在Bean的初始化方法执行后调用。
实操案例:给所有Bean添加自定义标记
// 实现BeanPostProcessor接口
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
// Bean初始化前执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 给所有以"Service"结尾的Bean添加标记
if (beanName.endsWith("Service")) {
System.out.println("BeanPostProcessor(前):" + beanName + ",准备初始化");
}
return bean; // 必须返回Bean对象,否则Bean会丢失
}
// Bean初始化后执行
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.endsWith("Service")) {
System.out.println("BeanPostProcessor(后):" + beanName + ",初始化完成");
}
return bean;
}
}
执行效果
启动应用后,控制台会输出:
BeanPostProcessor(前):userService,准备初始化
UserService:@PostConstruct初始化,加载用户缓存
BeanPostProcessor(后):userService,初始化完成
BeanPostProcessor(前):orderService,准备初始化
OrderService:InitializingBean初始化,初始化订单队列
BeanPostProcessor(后):orderService,初始化完成
3. 应用运行/关闭阶段扩展:ApplicationListener
作用
监听Spring Boot生命周期中的事件(如启动完成、关闭事件),在特定事件触发时执行自定义逻辑(如启动后打印日志、关闭前释放资源)。
核心事件(按生命周期顺序)
事件名称 | 触发时机 | 作用场景 |
---|---|---|
ApplicationStartingEvent |
应用启动开始(run() 方法刚执行) |
初始化日志、注册监听器 |
ApplicationEnvironmentPreparedEvent |
环境(Environment)准备完成 | 修改配置、添加环境变量 |
ApplicationContextInitializedEvent |
应用上下文创建并初始化完成 | 预处理应用上下文 |
ApplicationReadyEvent |
应用启动完成,可对外提供服务 | 打印启动成功日志、发送告警通知 |
ContextClosedEvent |
应用上下文关闭前 | 释放资源、关闭连接池 |
实操案例1:监听启动完成事件
// 方式1:实现ApplicationListener接口
@Component
public class StartupCompleteListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// 获取应用上下文与环境信息
ConfigurableApplicationContext context = event.getApplicationContext();</