自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring的Lifecycle和SmartLifecycle,可以沒用過(guò),但不能不知道!

開發(fā) 架構(gòu)
需要基于Spring容器的生命周期來(lái)處理一些邏輯時(shí),通??梢詫?shí)現(xiàn)SmartLifecycle接口來(lái)完成。像Spring Cloud,Spring Boot中都有大量的實(shí)踐案例。所以,無(wú)論實(shí)戰(zhàn)或閱讀源碼,不了解Lifecycle相關(guān)接口,都是一種損失。

[[401794]]

本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者二師兄。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。

前言

在使用Spring的過(guò)程中,我們通常會(huì)用@PostConstruct和@PreDestroy在Bean初始化或銷毀時(shí)執(zhí)行一些操作,這些操作屬于Bean聲明周期級(jí)別的。

那么,就存在一些遺漏的場(chǎng)景,比如我們想在容器本身的生命周期(比如容器啟動(dòng)、停止)的事件上做一些工作,很典型的就是Spring Boot中啟動(dòng)內(nèi)嵌的Web容器。該怎么辦?

這就需要用到Spring提供的另外一個(gè)接口Lifecycle。這篇文件就介紹一下Lifecycle接口,以及比它更聰明(Smart)的SmartLifecycle。

Lifecycle接口

Lifecycle是一個(gè)接口,它的作用是讓開發(fā)者可以在所有的bean都創(chuàng)建完成(getBean)之后執(zhí)行自己的初始化工作,或者在退出時(shí)執(zhí)行資源銷毀工作。

Lifecycle定義了三個(gè)方法,任何Bean實(shí)現(xiàn)了Lifecycle方法,當(dāng)ApplicationContext收到start、stop和restart等信號(hào)時(shí),就會(huì)調(diào)用對(duì)應(yīng)的方法。因此可以通過(guò)實(shí)現(xiàn)Lifecycle接口獲得容器生命周期的回調(diào),實(shí)現(xiàn)業(yè)務(wù)擴(kuò)展。

LifeCycle定義如下:

  1. public interface Lifecycle { 
  2.  
  3.     void start(); 
  4.  
  5.     void stop(); 
  6.  
  7.     boolean isRunning(); 

自定義Lifecycle實(shí)現(xiàn)類

首先我們來(lái)自定義一個(gè)類,實(shí)現(xiàn)Lifecycle接口,來(lái)看看具體的實(shí)踐效果:

  1. @Component 
  2. public class MyLifeCycle implements Lifecycle { 
  3.  
  4.     /** 
  5.      * 運(yùn)行狀態(tài) 
  6.      */ 
  7.     private volatile boolean running = false
  8.  
  9.     /** 
  10.      * 容器啟動(dòng)后調(diào)用 
  11.      */ 
  12.     @Override 
  13.     public void start() { 
  14.         System.out.println("容器啟動(dòng)后執(zhí)行MyLifeCycle操作..."); 
  15.         running = true
  16.     } 
  17.  
  18.     /** 
  19.      * 容器停止時(shí)調(diào)用 
  20.      */ 
  21.     @Override 
  22.     public void stop() { 
  23.         System.out.println("收到關(guān)閉容器的信號(hào)MyLifeCycle操作..."); 
  24.         running = false
  25.     } 
  26.  
  27.     /** 
  28.      * 檢查此組件是否正在運(yùn)行。 
  29.      * 1. 只有該方法返回false時(shí),start方法才會(huì)被執(zhí)行。 
  30.      * 2. 只有該方法返回true時(shí),stop(Runnable callback)或stop()方法才會(huì)被執(zhí)行。 
  31.      */ 
  32.     @Override 
  33.     public boolean isRunning() { 
  34.         System.out.println("檢查MyLifeCycle組件的運(yùn)行狀態(tài):" + running); 
  35.         return running; 
  36.     } 

單純的將上述代碼添加的Spring Boot項(xiàng)目當(dāng)中,你會(huì)發(fā)現(xiàn)啟動(dòng)時(shí)并沒有打印出任何相關(guān)的日志,只有在關(guān)閉應(yīng)用時(shí)會(huì)打印出:

  1. 檢查MyLifeCycle組件的運(yùn)行狀態(tài):false 

這是因?yàn)?,在SpringBoot或Spring應(yīng)用中如果沒有調(diào)用AbstractApplicationContext#start方法,只是實(shí)現(xiàn)了Lifecycle接口,是不會(huì)執(zhí)行Lifecycle接口中的啟動(dòng)方法和isRunning方法的。但在應(yīng)用退出時(shí)會(huì)執(zhí)行Lifecycle#isRunning方法判斷該Lifecycle是否已經(jīng)啟動(dòng),如果返回true則調(diào)用Lifecycle#stop()停止方法。

這個(gè)實(shí)例有一個(gè)很明顯的問題,那就是需要使用者顯式的調(diào)用容器的start()和stop()方法,Lifecycle的接口方法才會(huì)被執(zhí)行。

而在一般的項(xiàng)目中,我們很少這樣顯式的去調(diào)用,所以就需要一個(gè)更“聰明”的類來(lái)處理,這就是SmartLifecycle。

SmartLifecycle

SmartLifecycle繼承自Lifecycle,提供了更豐富的功能:第一,start()方法無(wú)需容器顯式調(diào)用就可以被執(zhí)行;第二,可以控制多SmartLifecycle實(shí)例的執(zhí)行順序。

先來(lái)看一下SmartLifecycle接口的源碼:

  1. public interface SmartLifecycle extends Lifecycle, Phased { 
  2.     int DEFAULT_PHASE = 2147483647; 
  3.  
  4.     default boolean isAutoStartup() { 
  5.         return true
  6.     } 
  7.  
  8.     default void stop(Runnable callback) { 
  9.         this.stop(); 
  10.         callback.run(); 
  11.     } 
  12.  
  13.     default int getPhase() { 
  14.         return 2147483647; 
  15.     } 

可以看出該接口除了繼承Lifecycle接口外,還繼承了Phased。其中g(shù)etPhase方法便是來(lái)自Phased。也正是基于Phased接口的這個(gè)方法來(lái)控制SmartLifecycle的執(zhí)行順序的。

來(lái)看一下實(shí)例代碼:

  1. @Component 
  2. public class MySmartLifecycle implements SmartLifecycle { 
  3.  
  4.     private volatile boolean running = false
  5.  
  6.     /** 
  7.      * 如果該`Lifecycle`類所在的上下文在調(diào)用`refresh`時(shí),希望能夠自己自動(dòng)進(jìn)行回調(diào),則返回`true`, 
  8.      * false的值表明組件打算通過(guò)顯式的start()調(diào)用來(lái)啟動(dòng),類似于普通的Lifecycle實(shí)現(xiàn)。 
  9.      */ 
  10.     @Override 
  11.     public boolean isAutoStartup() { 
  12.         return true
  13.     } 
  14.  
  15.     /** 
  16.      * SmartLifecycle子類的才有的方法,當(dāng)isRunning方法返回true時(shí),該方法才會(huì)被調(diào)用。 
  17.      * 很多框架中的源碼中,都會(huì)把真正邏輯寫在stop()方法內(nèi)。 
  18.      * 比如quartz和Redis的spring支持包。 
  19.      */ 
  20.     @Override 
  21.     public void stop(Runnable callback) { 
  22.         System.out.println("MySmartLifecycle容器停止,執(zhí)行回調(diào)函數(shù)"); 
  23.         stop(); 
  24.         // 如果你讓isRunning返回true,需要執(zhí)行stop這個(gè)方法,那么就不要忘記調(diào)用callback.run()。 
  25.         // 否則在程序退出時(shí),Spring的DefaultLifecycleProcessor會(huì)認(rèn)為這個(gè)MySmartLifecycle沒有stop完成,程序會(huì)一直卡著結(jié)束不了,等待一定時(shí)間(默認(rèn)超時(shí)時(shí)間30秒)后才會(huì)自動(dòng)結(jié)束。 
  26.         callback.run(); 
  27.     } 
  28.  
  29.     /** 
  30.      * 1. 主要在該方法中啟動(dòng)任務(wù)或者其他異步服務(wù),比如開啟MQ接收消息<br/> 
  31.      * 2. 當(dāng)上下文被刷新(所有對(duì)象已被實(shí)例化和初始化之后)時(shí),將調(diào)用該方法, 
  32.      * 默認(rèn)生命周期處理器將檢查每個(gè)SmartLifecycle對(duì)象的isAutoStartup()方法返回的布爾值。 
  33.      * 如果為“true”,則該方法會(huì)被調(diào)用,而不是等待顯式調(diào)用自己的start()方法。 
  34.      */ 
  35.     @Override 
  36.     public void start() { 
  37.         System.out.println("MySmartLifecycle容器啟動(dòng)完成 ..."); 
  38.         running = true
  39.     } 
  40.  
  41.     /** 
  42.      * 接口Lifecycle子類的方法,只有非SmartLifecycle的子類才會(huì)執(zhí)行該方法。<br/> 
  43.      * 1. 該方法只對(duì)直接實(shí)現(xiàn)接口Lifecycle的類才起作用,對(duì)實(shí)現(xiàn)SmartLifecycle接口的類無(wú)效。<br/> 
  44.      * 2. 方法stop()和方法stop(Runnable callback)的區(qū)別只在于,后者是SmartLifecycle子類的專屬。 
  45.      */ 
  46.     @Override 
  47.     public void stop() { 
  48.         System.out.println("MySmartLifecycle容器停止 ..."); 
  49.         running = false
  50.     } 
  51.  
  52.     /** 
  53.      * 1. 只有該方法返回false時(shí),start方法才會(huì)被執(zhí)行。<br/> 
  54.      * 2. 只有該方法返回true時(shí),stop(Runnable callback)或stop()方法才會(huì)被執(zhí)行。 
  55.      */ 
  56.     @Override 
  57.     public boolean isRunning() { 
  58.         System.out.println("MySmartLifecycle檢查運(yùn)行狀態(tài) ..."); 
  59.         return running; 
  60.     } 
  61.  
  62.     /** 
  63.      * 如果有多個(gè)實(shí)現(xiàn)接口SmartLifecycle的類,則這些類的start的執(zhí)行順序按getPhase方法返回值從小到大執(zhí)行。<br/> 
  64.      * 例如:1比2先執(zhí)行,-1比0先執(zhí)行。stop方法的執(zhí)行順序則相反,getPhase返回值較大類的stop方法先被調(diào)用,小的后被調(diào)用。 
  65.      * 
  66.      */ 
  67.     @Override 
  68.     public int getPhase() { 
  69.         return 0; 
  70.     } 

關(guān)于每個(gè)方法的功能,注釋部分已經(jīng)明確說(shuō)明了,下面啟動(dòng)SpringBoot項(xiàng)目,打印日志如下:

  1. MySmartLifecycle檢查運(yùn)行狀態(tài) ... 
  2. MySmartLifecycle容器啟動(dòng)完成 ... 

關(guān)閉SpringBoot項(xiàng)目,打印日志如下:

  1. MySmartLifecycle檢查運(yùn)行狀態(tài) ... 
  2. MySmartLifecycle容器停止,執(zhí)行回調(diào)函數(shù) 
  3. MySmartLifecycle容器停止 ... 

通過(guò)上述實(shí)例可以看出:如果一個(gè)Bean實(shí)現(xiàn)了SmartLifecycle接口,則會(huì)執(zhí)行啟動(dòng)方法。SmartLifecycle#isRunning判斷是否已經(jīng)執(zhí)行,返回false表示還未執(zhí)行,則調(diào)用SmartLifecycle#start()執(zhí)行。

當(dāng)關(guān)閉時(shí),同樣先檢查運(yùn)行狀態(tài),如果正在運(yùn)行,則執(zhí)行關(guān)閉操作。關(guān)閉時(shí),還可以處理對(duì)應(yīng)的回調(diào)函數(shù)。

其中,Phased返回值越小,優(yōu)先級(jí)越高。

小結(jié)

 

當(dāng)需要基于Spring容器的生命周期來(lái)處理一些邏輯時(shí),通常可以實(shí)現(xiàn)SmartLifecycle接口來(lái)完成。像Spring Cloud,Spring Boot中都有大量的實(shí)踐案例。所以,無(wú)論實(shí)戰(zhàn)或閱讀源碼,不了解Lifecycle相關(guān)接口,都是一種損失。本文的產(chǎn)生也是在遇到Spring Cloud集成Nacos的源碼中獲得的靈感。

 

責(zé)任編輯:武曉燕 來(lái)源: 程序新視界
相關(guān)推薦

2017-12-25 13:26:36

CNN深度學(xué)習(xí)網(wǎng)絡(luò)

2019-07-08 10:40:03

線程池策略CPU

2020-08-18 10:51:18

AIoT數(shù)據(jù)泄露網(wǎng)絡(luò)攻擊

2024-06-03 00:00:05

2016-12-15 17:15:44

2017-01-16 15:01:27

中安威士

2017-01-19 14:44:14

2009-08-03 09:29:26

2018-04-16 10:54:00

數(shù)據(jù)中心UPS電池

2009-06-22 14:17:00

2022-01-05 08:01:48

前端技術(shù)編程

2012-09-17 09:59:46

創(chuàng)業(yè)創(chuàng)業(yè)教訓(xùn)創(chuàng)業(yè)家

2019-11-13 08:37:34

數(shù)據(jù)庫(kù)筒倉(cāng)基礎(chǔ)架構(gòu)

2010-04-12 16:59:52

Oracle性能診斷

2017-05-04 11:05:43

互聯(lián)網(wǎng)

2010-06-01 09:48:43

云計(jì)算CIO整合

2009-12-21 15:43:07

2022-02-28 09:44:39

JDKJavaSpring

2012-11-23 10:57:44

Shell

2009-12-11 13:33:36

VS2008技巧
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)