在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> {@Overridepublic 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);// 添加自定義Initializerapplication.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 {// 模擬屬性注入@Autowiredprivate UserDao userDao;// 初始化方法:在屬性注入后執行@PostConstructpublic void init() {System.out.println("UserService:@PostConstruct初始化,加載用戶緩存");// 模擬初始化邏輯userDao.loadCache();}
}
(2)InitializingBean:Bean初始化接口
作用
與@PostConstruct
類似,通過實現接口方法定義Bean的初始化邏輯,優先級低于@PostConstruct
(@PostConstruct
先執行)。
實操案例
@Component
public class OrderService implements InitializingBean {@Autowiredprivate OrderDao orderDao;@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("OrderService:InitializingBean初始化,初始化訂單隊列");// 模擬初始化邏輯orderDao.initQueue();}
}
執行順序驗證
若一個Bean同時使用@PostConstruct
和InitializingBean
:
@Component
public class ProductService implements InitializingBean {@PostConstructpublic void postConstructInit() {System.out.println("ProductService:@PostConstruct執行");}@Overridepublic 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初始化前執行@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 給所有以"Service"結尾的Bean添加標記if (beanName.endsWith("Service")) {System.out.println("BeanPostProcessor(前):" + beanName + ",準備初始化");}return bean; // 必須返回Bean對象,否則Bean會丟失}// Bean初始化后執行@Overridepublic 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> {@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {// 獲取應用上下文與環境信息ConfigurableApplicationContext context = event.getApplicationContext();</