Spring SmartLifecycle:如何精準(zhǔn)控制Bean的生命周期
一、核心作用
SmartLifecycle 是 Spring 框架中用于 精確控制組件生命周期階段 的高級(jí)接口,主要解決三類問題:
- 有序啟停:控制多個(gè)組件啟動(dòng)/關(guān)閉順序
- 階段化處理:將初始化/銷毀操作劃分為不同階段
- 上下文感知:獲取應(yīng)用上下文狀態(tài)變化事件
二、典型應(yīng)用場(chǎng)景
場(chǎng)景 | 具體用途 | 優(yōu)勢(shì)體現(xiàn) |
---|---|---|
連接池管理 | 數(shù)據(jù)庫(kù)/Redis連接池的預(yù)熱和優(yōu)雅關(guān)閉 | 避免連接泄漏 |
線程池控制 | 異步線程池的初始化與任務(wù)排空 | 防止任務(wù)丟失 |
外部服務(wù)注冊(cè) | 服務(wù)注冊(cè)中心的上線通知與下線注銷 | 保證服務(wù)狀態(tài)一致性 |
定時(shí)任務(wù)調(diào)度 | 分布式任務(wù)調(diào)度器的啟動(dòng)與暫停 | 精準(zhǔn)控制任務(wù)執(zhí)行周期 |
硬件設(shè)備控制 | IoT設(shè)備連接初始化與安全斷開 | 保障設(shè)備操作安全性 |
三、核心方法詳解
public interface SmartLifecycle extends Lifecycle { // 關(guān)鍵方法1:?jiǎn)?dòng)組件(自動(dòng)觸發(fā)) void start(); // 關(guān)鍵方法2:停止組件(帶異步通知) default void stop(Runnable callback) { stop(); callback.run(); } // 關(guān)鍵方法3:相位控制(數(shù)值越小優(yōu)先級(jí)越高) int getPhase(); // 其他方法 boolean isAutoStartup(); boolean isRunning(); }
四、實(shí)戰(zhàn)代碼示例
基本案例:
@Component public class DatabaseConnector implements SmartLifecycle { private volatile boolean running = false; private ConnectionPool pool; @Override public void start() { if (!running) { this.pool = initConnectionPool(); // 連接池預(yù)熱 running = true; } } @Override public void stop() { if (running) { pool.safeRelease(); // 安全釋放連接 running = false; } } @Override public int getPhase() { return Integer.MIN_VALUE + 1000; // 高優(yōu)先級(jí)組件 } }
主動(dòng)結(jié)束當(dāng)前線程的處理案例:
@Slf4j @Configuration public class SensitiveWordsConfiguration implements SmartLifecycle { /** * lifeRunning */ private volatile boolean lifeRunning = false; /** * 更新時(shí)間間隔 */ private static final long UPDATE_TIME_SECONDS = 10 * 60; /** * 是否終止線程 */ private volatile boolean threadStop = false; /** * taskExecutor */ @Autowired private ThreadPoolTaskExecutor taskExecutor; /** * 當(dāng)前線程任務(wù) */ private Future<?> future; /** * 實(shí)現(xiàn)熱更新,修改詞典后自動(dòng)加載 */ private void startScheduledUpdate() { while (!threadStop && !Thread.currentThread().isInterrupted()) { try { log.debug("SensitiveWordConfig#startScheduledUpdate start update..."); //這里做業(yè)務(wù)處理 //... TimeUnit.SECONDS.sleep(UPDATE_TIME_SECONDS); } catch (InterruptedException e) { log.info("SensitiveWordConfig#startScheduledUpdate interrupted: {}", e.getMessage()); Thread.currentThread().interrupt(); break; } } } @Override public void start() { // 啟動(dòng)定時(shí)更新任務(wù)線程 this.future = taskExecutor.submit(this::startScheduledUpdate); lifeRunning = true; } @Override public void stop() { threadStop = true; // 主動(dòng)終止當(dāng)前線程的(否則會(huì)持續(xù)sleep直到線程池shutdownNow導(dǎo)致占用停止時(shí)間) this.future.cancel(true); lifeRunning = false; } @Override public boolean isRunning() { return lifeRunning; } }
要特別注意的是:這個(gè)案例中使用了spring上下文中的 ThreadPoolTaskExecutor,所以不能使用 @PreDestroy 注解方法來(lái)進(jìn)行回收處理,因?yàn)閟pring在關(guān)閉容器時(shí)會(huì)先對(duì)上下問中的線程池進(jìn)行shutdown完成后,才會(huì)執(zhí)行所有bean的destroy方法。
五、相位控制策略
通過 getPhase()
返回值控制執(zhí)行順序:
- 啟動(dòng)順序:相位值 從小到大 執(zhí)行
- 關(guān)閉順序:相位值 從大到小 執(zhí)行
六、與普通Lifecycle的區(qū)別
特性 | Lifecycle | SmartLifecycle |
---|---|---|
自動(dòng)啟動(dòng) | ? 需手動(dòng)觸發(fā) | ? 支持自動(dòng)啟動(dòng) |
停止回調(diào) | ? 無(wú) | ? 帶異步完成通知 |
執(zhí)行順序控制 | ? 不支持 | ? 相位值精確控制 |
上下文刷新集成 | ? 有限支持 | ? 深度集成上下文生命周期 |
七、注意事項(xiàng)
- 異常處理:在
start()
/stop()
中必須捕獲異常,避免阻斷全局生命周期流程 - 線程安全:確保實(shí)現(xiàn)類方法的線程安全性
- 性能影響:避免在生命周期方法中執(zhí)行耗時(shí)操作(>1秒的操作建議異步化)
- 容器兼容:與
@PostConstruct
/@PreDestroy
注解配合使用時(shí)注意執(zhí)行順序。執(zhí)行順序@PostConstruct
>start()
>stop()
>@PreDestroy
。
通過合理使用 SmartLifecycle,可以實(shí)現(xiàn) 服務(wù)零中斷重啟、資源按序回收 等高級(jí)功能,是構(gòu)建企業(yè)級(jí) Spring 應(yīng)用的必備技能。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot 監(jiān)聽Redis鍵過期事件(過期監(jiān)聽)
Redis鍵過期事件是SpringBoot中常用的緩存失效通知方式,通過配置可以監(jiān)聽特定鍵的過期事件,具有一定的參考價(jià)值,感興趣的可以了解一下2024-12-12PowerJob的HashedWheelTimer工作流程源碼解讀
這篇文章主要為大家介紹了PowerJob的HashedWheelTimer工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01java中switch條件語(yǔ)句的三種語(yǔ)法、用法及支持的參數(shù)類型
Java中的switch語(yǔ)句是一種多分支選擇結(jié)構(gòu),可以一個(gè)變量的值改變程序的控制流,這篇文章主要給大家介紹了關(guān)于java中switch條件語(yǔ)句的三種語(yǔ)法、用法及支持的參數(shù)類型的相關(guān)資料,需要的朋友可以參考下2024-06-06Java中冒泡排序的原生實(shí)現(xiàn)方法(正序與逆序)
這篇文章主要給大家介紹了關(guān)于Java中冒泡排序的原生實(shí)現(xiàn)方法(正序與逆序)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Java導(dǎo)出多個(gè)excel表打包到zip文件中供客戶端另存為窗口下載實(shí)現(xiàn)方法
最近的項(xiàng)目有一個(gè)導(dǎo)出匯總數(shù)據(jù)的要求,考慮到用戶軟件的差異,所以要分別導(dǎo)出xls以及xlsx并且打包提供下載,下面這篇文章主要給大家介紹了關(guān)于Java導(dǎo)出多個(gè)excel表打包到zip文件中供客戶端另存為窗口下載的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-12-12基于@RestControllerAdvice與@ControllerAdvice的區(qū)別說(shuō)明
這篇文章主要介紹了@RestControllerAdvice與@ControllerAdvice的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例
這篇文章主要介紹了JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07