天天看點

tomcat生命周期的管理——生命周期統一接口Lifecycle

我們知道Tomcat的架構設計是清晰的、子產品化的,其擁有很多元件,假如我們要啟動Tomcat,可以一個一個啟動元件,但這樣啟動有很多缺點,不僅麻煩,而且容易漏了元件啟動,還會對後面動态元件擴充帶來麻煩。難不成真要我們一個一個啟動嗎?其實未必,Tomcat的設計者提供了一個解決方案:用Lifecycle管理啟動、停止、關閉。

從第一節的架構圖可以看到各個核心元件有包含與被包含的關系,例如Server<-Service<-Container和Connector,最大的是Server,往下一層層包含。其實Tomcat就是以容器的方式來組織整個系統架構的,反映到資料結構就是樹,樹的根節點沒有父節點,其它節點有且僅有一個父節點,每個父節點有零個或多個子節點,根容器與其他容器也有這樣的特點。鑒于如此,可以通過父容器負責啟動它的子容器,這樣隻要啟動根容器,即可把其他所有容器都啟動,達到統一啟動、停止、關閉的效果。

Lifecycle作為統一的接口,把所有的啟動、停止、關閉、生命周期相關方法都組織到一起,就可以很友善地管理Tomcat各個容器元件的生命周期。下面是Lifecycle接口詳細的定義:

public interface Lifecycle {

   public static final String BEFORE_INIT_EVENT = "before_init";

   public static final String AFTER_INIT_EVENT = "after_init";

   public static final String START_EVENT = "start";

   public static final String BEFORE_START_EVENT ="before_start";

   public static final String AFTER_START_EVENT = "after_start";

   public static final String STOP_EVENT = "stop";

   public static final String BEFORE_STOP_EVENT = "before_stop";

   public static final String AFTER_STOP_EVENT = "after_stop";

   public static final String AFTER_DESTROY_EVENT ="after_destroy";

   public static final String BEFORE_DESTROY_EVENT ="before_destroy";

   public static final String PERIODIC_EVENT = "periodic";

   public static final String CONFIGURE_START_EVENT ="configure_start";

   public static final String CONFIGURE_STOP_EVENT ="configure_stop";

   public void addLifecycleListener(LifecycleListener listener);

   public LifecycleListener[] findLifecycleListeners();

   public void removeLifecycleListener(LifecycleListener listener);

   public void init() throws LifecycleException;

   public void start() throws LifecycleException;

   public void stop() throws LifecycleException;

   public LifecycleState getState();

   public String getStateName();

}

從上面可以看出Lifecycle其實就是定義了一些狀态常量跟幾個方法,這裡主要看下init、start、stop三個方法,所有需要被生命周期管理的容器都要實作這個接口,并且各自被父容器的相應方法調用,例如在初始化階段,根容器Server會調用init方法,而在init方法裡會調用它的子容器Service的init方法,以此類推。

在實際使用中,一般隻有統一實作Lifecycle接口後才能實作統一調用,例如調用容器的init方法是這樣子:((Lifecycle)容器).init()。下面簡單看看Tomcat源碼的Server是怎樣調用init的。

publicfinalsynchronizedvoid init()throws LifecycleException {

……

for (int i = 0; i < services.length; i++) {

           services[i].init();

       }

 ……

Server容器裡面有若幹多個Service執行個體,那麼隻要用一個for循環即可分别讓每個Service調用init方法。這裡的services[i]并沒有用(Lifecycle)顯式轉換類型,其實是因為Service也是一個接口,而這個接口已經繼承了Lifecycle接口。

同樣的,啟動跟停止步驟也是通過類似的調用實作統一啟動統一關閉。至此,我們對Tomcat的生命周期統一初始化、啟動、關閉機制有了比較清晰的認識。

<a target="_blank" href="https://item.jd.com/12185360.html">點選訂購作者《Tomcat核心設計剖析》</a>

繼續閱讀