Tomcat生命周期管理 各種組件如何統一管理 Tomcat的架構設計是清晰的、模塊化、它擁有很多組件,加入在啟動Tomcat時一個一個組件啟動,很容易遺漏組件,同時還會對後面的動態組件拓展帶來麻煩。如果採用我們傳統的方式的話,組件在啟動過程中如果發生異常,會很難管理,比如你的下一個組件調用了sta ...
Tomcat生命周期管理
各種組件如何統一管理
Tomcat的架構設計是清晰的、模塊化、它擁有很多組件,加入在啟動Tomcat時一個一個組件啟動,很容易遺漏組件,同時還會對後面的動態組件拓展帶來麻煩。如果採用我們傳統的方式的話,組件在啟動過程中如果發生異常,會很難管理,比如你的下一個組件調用了start方法,但是如果它的上級組件還沒有start甚至還沒有init的話,Tomcat的啟動會非常難管理,因此,Tomcat的設計者提出一個解決方案:用Lifecycle管理啟動,停止、關閉。
生命周期統一介面
Tomcat內部架構中各個核心組件有包含與被包含關係,例如:Server包含了Service.Service又包含了Container和Connector,這個結構有一點像數據結構中的樹,樹的根結點沒有父節點,其他節點有且僅有一個父節點,每一個父節點有0至多個子節點。所以,我們可以通過父容器啟動它的子容器,這樣只要啟動根容器,就可以把其他所有的容器都啟動,從而達到了統一的啟動,停止、關閉的效果。
所有所有組件有一個統一的介面——Lifecycle,把所有的啟動、停止、關閉、生命周期相關的方法都組織到一起,就可以很方便管理Tomcat各個容器組件的生命周期。
Lifecycle其實就是定義了一些狀態常量和幾個方法,主要方法是init,start,stop三個方法。
例如:Tomcat的Server組件的init負責遍歷調用其包含所有的Service組件的init方法。
註意:Server只是一個介面,實現類為StandardServer,有意思的是,StandardServer沒有init方法,init方法是在哪裡,其實是在它的父類LifecycleBase中,這個類就是統一的生命周期管理。
COPYpublic class StandardService extends LifecycleMBeanBase implements Service
public abstract class LifecycleMBeanBase extends LifecycleBase
implements JmxEnabled
LifecycleBase
COPYpublic abstract class LifecycleBase implements Lifecycle {
@Override
public final synchronized void init() throws LifecycleException {
//這個就是為了防止 組件啟動的順序不對
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
//只列印核心組件
if(this.getClass().getName().startsWith("org.apache.catalina.core")||this.getClass().getName().startsWith("org.apache.catalina.connector")){
System.out.println(this.getClass()+"--init()");
}
setStateInternal(LifecycleState.INITIALIZING, null, false);
//調用子類的initInternal方法
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}
}
所以StandardServer最終只會調用到initInternal方法,這個方法會初始化子容器Service的init方法
為什麼LifecycleBase這麼玩,其實很多架構源碼都是這麼玩的,包括JDK的容器源碼都是這麼玩的,一個類,有一個介面,同時抽象一個抽象骨架類,把通用的實現放在抽象骨架類中,這樣設計就方便組件的管理,使用LifecycleBase骨架抽象類,在抽象方法中就可以進行統一的處理。
LifeCycle源碼分析
作用
組件生命周期方法的通用介面。 Catalina組件可以實現此介面(以及它們支持的功能的適當介面),以便提供一致的機制來啟動和停止組件
狀態圖
Tomcat中的事件觸發是通過這些狀態來判定的。
COPY* start()
* -----------------------------
* | |
* | init() |
* NEW -»-- INITIALIZING |
* | | | | ------------------«-----------------------
* | | |auto | | |
* | | \|/ start() \|/ \|/ auto auto stop() |
* | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
* | | | | |
* | |destroy()| | |
* | --»-----«-- ------------------------«-------------------------------- ^
* | | | |
* | | \|/ auto auto start() |
* | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
* | \|/ ^ | ^
* | | stop() | | |
* | | -------------------------- | |
* | | | | |
* | | | destroy() destroy() | |
* | | FAILED ----»------ DESTROYING ---«----------------- |
* | | ^ | |
* | | destroy() | |auto |
* | --------»----------------- \|/ |
* | DESTROYED |
* | |
* | stop() |
* ----»-----------------------------»------------------------------
介面定義
Lifecycle介面統一管理Tomcat生命周期。一共做了4件事:
- 定義13個string類型常量,用於LifecycleEvent時間的type屬性中,用於區分組件發出的LifecycleEvent事件時的狀態。
- 定義三個管理監聽器的方法,addLifecycleListener、findLifecycleListeners、removeLifecycleListener。
- 定義4個生命周期的方法,init、start、stop、destory,用於執行生命周期的各個階段的操作。
- 定義了獲取當前狀態的兩個方法,getState、getStateName、用於獲取當前的狀態。
COPYpublic interface Lifecycle {
// 13個狀態常量值
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";
// 3個監聽器方法
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
// 4個生命周期方法
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
// 2個當前狀態方法
public LifecycleState getState();
public String getStateName();
}
預設實現類
COPYpublic abstract class LifecycleBase implements Lifecycle {
// 源組件的當前狀態,不同狀態觸發不同事件
private volatile LifecycleState state = LifecycleState.NEW;
}
監聽器相關方法
事件監聽器需要三個參與者:
- 事件對象:用於封裝事件的信息,在事件監聽器介面的同一方法中作為參數使用,繼承自java.util.EventObject類。
- 事件源:觸發事件的源頭,不同事件源觸發不同事件類型。
- 事件監聽器:負責監聽事件源發出的事件。實現 java.util.EventListener 介面。
COPY// 用於事件通知的已註冊LifecycleListener列表
private final List<LifecycleListener> lifecycleListeners =
new CopyOnWriteArrayList<>();
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}
@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
// 子類根據當前狀態觸發不同事件,實現不同操作
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
生命周期方法
LifecycleBase 類是Lifecycle 介面的預設實現,所有實現了生命周期的組件都直接或者間接的繼承自LifecycleBase。
init方法
COPY@Override
public final synchronized void init() throws LifecycleException {
// 只有 NEW 狀態可以調用
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
// 設置 生命周期狀態 -- INITIALIZING,觸發相應事件
setStateInternal(LifecycleState.INITIALIZING, null, false);
// 模板方法,由具體子類實現
initInternal();
// 執行完成,設置生命周期狀態 -- INITIALIZED,觸發相應事件
setStateInternal(LifecycleState.INITIALIZED, null, false);
}
Start方法
COPY@Override
public final synchronized void start() throws LifecycleException {
// 此三種狀態不執行
if (LifecycleState.STARTING_PREP.equals(state) ||
LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
return;
}
// NEW 狀態 執行 init 方法
if (state.equals(LifecycleState.NEW)) {
init();
// 啟動失敗,調用 stop 方法
} else if (state.equals(LifecycleState.FAILED)) {
stop();
// 其它狀態,非法操作
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
throw new LifecycleException()
}
// 設置啟動狀態為 STARTING_PREP【開始準備】
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
// 調用完成後判斷組件啟動狀態
if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
throw new LifecycleException();
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
}
stop方法
COPY@Override
public final synchronized void stop() throws LifecycleException {
// STOPPING_PREP、STOPPING、STOPPED此三種狀態不予執行
if (LifecycleState.STOPPING_PREP.equals(state) ||
LifecycleState.STOPPING.equals(state) ||
LifecycleState.STOPPED.equals(state)) {
return;
}
// 如果狀態為 NEW、修改為 STOPPED
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
// 不為 STARTED、FAILED 2種狀態,拋出異常
if (!state.equals(LifecycleState.STARTED) &&
!state.equals(LifecycleState.FAILED)) {
throw new LifecycleException();
}
try {
// 啟動失敗,觸發事件,否則設置生命周期狀態
if (state.equals(LifecycleState.FAILED)) {
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
// 調用模板方法
stopInternal();
if (!state.equals(LifecycleState.STOPPING) &&
!state.equals(LifecycleState.FAILED)) {
throw new LifecycleException();
}
setStateInternal(LifecycleState.STOPPED, null, false);
} catch (Throwable t) {
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException();
} finally {
if (this instanceof Lifecycle.SingleUse) {
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}
destroy方法
COPY@Override
public final synchronized void destroy() throws LifecycleException {
// 啟動失敗,先調用 stop 方法
if (LifecycleState.FAILED.equals(state)) {
stop();
}
// DESTROYING、DESTROYED不執行了
if (LifecycleState.DESTROYING.equals(state) ||
LifecycleState.DESTROYED.equals(state)) {
return;
}
// 非法狀態
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
throw new LifecycleException();
}
try {
setStateInternal(LifecycleState.DESTROYING, null, false);
destroyInternal();
setStateInternal(LifecycleState.DESTROYED, null, false);
} catch (Throwable t) {
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException();
}
}
設置狀態方法
COPYprivate synchronized void setStateInternal(LifecycleState state,
Object data, boolean check) throws LifecycleException {
// 檢查參數
if (check) {
if (state == null) {
throw new LifecycleException();
return;
}
if (!(state == LifecycleState.FAILED ||
(this.state == LifecycleState.STARTING_PREP &&
state == LifecycleState.STARTING) ||
(this.state == LifecycleState.STOPPING_PREP &&
state == LifecycleState.STOPPING) ||
(this.state == LifecycleState.FAILED &&
state == LifecycleState.STOPPING))) {
throw new LifecycleException();
}
}
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
監聽機制
事件監聽器需要三個參與者:
- 事件對象—用於封裝事件的信息,在事件監聽器介面的統一方法中作為參數,一般繼承 java.util.EventObjecct類。
- 事件源—觸發事件對的源頭,不同事件源觸發不同事件。
- 事件監聽器—負責監聽事件源發出的事件,發生事件時,事件源調用事件監聽器的統一方法處理。監聽器一般實現java.util.EventListener介面。
COPYpublic final class LifecycleEvent extends java.util.EventObject {
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.type = type;
this.data = data;
}
}
COPYpublic interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}
COPYpublic class HostConfig implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
try {
host = (Host) event.getLifecycle();
if (host instanceof StandardHost) {
setCopyXML(((StandardHost) host).isCopyXML());
setDeployXML(((StandardHost) host).isDeployXML());
setUnpackWARs(((StandardHost) host).isUnpackWARs());
setContextClass(((StandardHost) host).getContextClass());
}
} catch (ClassCastException e) {
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
check();
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
} else if (event.getType().equals(Lifecycle.START_EVENT)) {
start();
} else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
stop();
}
}
}
COPY// LifecycleBase.startInternal
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
模板方法
四個模板方法,由子類具體實現
COPYprotected abstract void initInternal() throws LifecycleException;
protected abstract void startInternal() throws LifecycleException;
protected abstract void stopInternal() throws LifecycleException;
protected abstract void destroyInternal() throws LifecycleException;
總結
通過提供init、start、stop、destory方法,通過相應的模板方法【模板設計模式】,提供組件的統一生命周期的管理、事件調度。
本文由
傳智教育博學谷狂野架構師
教研團隊發佈。如果本文對您有幫助,歡迎
關註
和點贊
;如果您有任何建議也可留言評論
或私信
,您的支持是我堅持創作的動力。轉載請註明出處!