Tomcat生命周期詳解
引言
在上篇文章中我們看到了Tomcat架構(gòu)中的核心組件,而且各個(gè)組件都有各自的作用,各司其職,而且相互之間也有對應(yīng)的父子關(guān)系,那么這些對象的創(chuàng)建,調(diào)用,銷毀等操作是怎么處理呢?

也就是在Tomcat中的組件的對象生命周期是怎么管理的呢?針對這個(gè)問題,在Tomcat中設(shè)計(jì)了Lifecycle接口來統(tǒng)一管理Tomcat中的核心組件的生命周期,所以本文我們就系統(tǒng)的來介紹下Lifecycle接口的設(shè)計(jì)
1、LifeCycle接口設(shè)計(jì)
為了統(tǒng)一管理Tomcat中的核心組件的生命周期,而專門設(shè)計(jì)了LifeCycle接口來統(tǒng)一管理,我們來看看在LifeCycle接口中聲明了哪些內(nèi)容。
1.1 生命周期的方法
在LifeCycle中聲明了和生命周期相關(guān)的方法,包括init(),start(),stop(),destory()等方法。

在聲明的方法執(zhí)行的過程中會涉及到對應(yīng)的狀態(tài)的轉(zhuǎn)換,在LifeCycle接口的頭部文檔中很清楚的說了。

1.2 相關(guān)的狀態(tài)處理
通過上圖我們可以很清楚的看到相關(guān)的方法執(zhí)行會涉及到的相關(guān)狀態(tài)的轉(zhuǎn)換,比如init()會從New這個(gè)狀態(tài)開始,然后會進(jìn)入 INITIALIZING 和 INITIALIZED 等。因?yàn)檫@塊涉及到了對應(yīng)的狀態(tài)轉(zhuǎn)換,在Lifecycle中聲明了相關(guān)的狀態(tài)和事件的生命周期字符串。
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";
/**
* The LifecycleEvent type for the "periodic" event.
* 周期性事件(后臺線程定時(shí)執(zhí)行一些事情,比如:熱部署、熱替換)
*/
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";
在LifecycleState中建立了對應(yīng)關(guān)系

針對特定的事件就會有相關(guān)的監(jiān)聽器來監(jiān)聽處理。在Lifecycle中定義了相關(guān)的處理方法。
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
通過方法名稱我們就能很清楚該方法的相關(guān)作用,就不過程介紹了。然后來看下對應(yīng)的監(jiān)聽器和事件接口的對應(yīng)設(shè)計(jì)。
2.監(jiān)聽器和事件的設(shè)計(jì)
接下來看下LifecycleListener的設(shè)計(jì)。其實(shí)代碼非常簡單。
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
* 觸發(fā)監(jiān)聽器后要執(zhí)行邏輯的方法
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
然后來看下事件的接口
public final class LifecycleEvent extends EventObject {
private static final long serialVersionUID = 1L;
/**
* Construct a new LifecycleEvent with the specified parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
* @param data Event data (if any)
*/
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle); // 向上轉(zhuǎn)型,可接受一切實(shí)現(xiàn)了生命周期的組件
this.type = type;
this.data = data;
}
/**
* The event data associated with this event.
* 攜帶的額外的數(shù)據(jù),傳遞給監(jiān)聽器的數(shù)據(jù)
*/
private final Object data;
/**
* The event type this instance represents.
* 事件類型
*/
private final String type;
/**
* @return the event data of this event.
*/
public Object getData() {
return data;
}
/**
* @return the Lifecycle on which this event occurred.
*/
public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
}
/**
* @return the event type of this event.
*/
public String getType() {
return this.type;
}
}
也是非常簡單,不過多的贅述。
3.LifecycleBase
通過上面的介紹我們可以看到在Tomcat中設(shè)計(jì)了Lifecycle和LifecycleListener和LifecycleEvent來管理核心組件的生命周期,那么我們就需要讓每一個(gè)組件都實(shí)現(xiàn)相關(guān)的接口。這時(shí)你會發(fā)現(xiàn)交給子類的工作量其實(shí)是比較大的,不光要完成各個(gè)組件的核心功能,還得實(shí)現(xiàn)生命周期的相關(guān)處理,耦合性很強(qiáng),這時(shí)在Tomcat中給我們提供了一個(gè)LifecycleBase的抽象類,幫助我們實(shí)現(xiàn)了很多和具體業(yè)務(wù)無關(guān)的處理,來簡化了具體組件的業(yè)務(wù)。

3.1 事件處理
在上面的接口設(shè)計(jì)中對于監(jiān)聽對應(yīng)的事件處理是沒有實(shí)現(xiàn)的,在LifecycleBase把這塊很好的實(shí)現(xiàn)了,我們來看下。首先定義了一個(gè)容器來存儲所有的監(jiān)聽器
// 存儲了所有的實(shí)現(xiàn)了LifecycleListener接口的監(jiān)聽器 private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
同時(shí)提供了觸發(fā)監(jiān)聽的相關(guān)的方法,綁定了對應(yīng)的事件。
/**
* Allow sub classes to fire {@link Lifecycle} events.
* 監(jiān)聽器觸發(fā)相關(guān)的事件
* @param type Event type 事件類型
* @param data Data associated with event.
*/
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
已經(jīng)針對Listener相關(guān)的處理方法
// 添加監(jiān)聽器
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
// 查找所有的監(jiān)聽并轉(zhuǎn)換為了數(shù)組類型
@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}
// 移除某個(gè)監(jiān)聽器
@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
3.2 生命周期方法
在LifecycleBase中最核心的還是實(shí)現(xiàn)了Lifecycle中的生命周期方法,以init方法為例我們來看。
/**
* 實(shí)現(xiàn)了 Lifecycle 中定義的init方法
* 該方法和對應(yīng)的組件的狀態(tài)產(chǎn)生的關(guān)聯(lián)
* @throws LifecycleException
*/
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
// 無效的操作 只有狀態(tài)為 New 的才能調(diào)用init方法進(jìn)入初始化
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
// 設(shè)置狀態(tài)為初始化進(jìn)行中....同步在方法中會觸發(fā)對應(yīng)的事件
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal(); // 交給子類具體的實(shí)現(xiàn) 初始化操作
// 更新狀態(tài)為初始化完成 同步在方法中會觸發(fā)對應(yīng)的事件
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}
源碼解析:
- 我們看到首先會判斷當(dāng)前對象的state狀態(tài)是否為NEW,因?yàn)閕nit方法只能在NEW狀態(tài)下才能開始初始化
- 如果1條件滿足則會更新state的狀態(tài)為
INITIALIZED同時(shí)會觸發(fā)這個(gè)事件 - 然后initInternale()方法會交給子類具體去實(shí)現(xiàn),
- 等待子類處理完成后會把狀態(tài)更新為
INITIALIZED。
我們可以進(jìn)入setStateInternal方法查看最后的關(guān)鍵代碼:
// ....
this.state = state; // 更新狀態(tài)
// 根據(jù)狀態(tài)和事件的綁定關(guān)系獲取對應(yīng)的事件
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
// 發(fā)布對應(yīng)的事件
fireLifecycleEvent(lifecycleEvent, data);
}
可以看到和對應(yīng)的事件關(guān)聯(lián)起來了。init方法的邏輯弄清楚后,你會發(fā)現(xiàn)start方法,stop方法,destory方法的處理邏輯都是差不多的,可自行觀看。
而對應(yīng)的 initInternal()方法的邏輯我們需要在 Server Service Engine Connector等核心組件中再看,這個(gè)我們會結(jié)合Tomcat的啟動流程來帶領(lǐng)大家一起查看。
以上就是Tomcat生命周期詳解的詳細(xì)內(nèi)容,更多關(guān)于Tomcat生命周期的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Windwos下實(shí)現(xiàn)Nginx+Tomcat集群過程解析
這篇文章主要介紹了Windwos下實(shí)現(xiàn)Nginx+Tomcat集群過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
詳述 tomcat 中的 server.xml 配置文件示例
本文將通過實(shí)例,介紹server.xml中各個(gè)組件的配置,并詳細(xì)說明 Tomcat 各個(gè)核心組件的作用以及各個(gè)組件之間的相互關(guān)系。對tomcat server.xml 配置文件相關(guān)知識感興趣的朋友一起看看吧2017-08-08
解決tomcat部署時(shí)war和war exploded導(dǎo)致的問題
war包和warexploded模式的區(qū)別主要在于部署方式,war包是在項(xiàng)目發(fā)布時(shí)打包上傳,而warexploded模式則是直接將文件夾結(jié)構(gòu)上傳到服務(wù)器,支持熱部署,常用于開發(fā)階段,這種差異可能導(dǎo)致樣式和文件引用問題,如在不同電腦部署時(shí)路徑設(shè)置的不同2024-10-10
tomcat組件圖解 一個(gè)web服務(wù)器的架構(gòu)演化史
這篇文章主要介紹了tomcat組件圖解 一個(gè)web服務(wù)器的架構(gòu)演化史,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Jenkins+tomcat自動發(fā)布的熱部署/重啟及遇到的問題解決辦法(推薦)
這篇文章主要介紹了Jenkins+tomcat自動發(fā)布的熱部署/重啟及遇到的問題解決辦法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07

