在上面的部分,其實咱們已經接觸到Tomcat的生命週期了,接下來咱們將仔細討論和學習Tomcat的生命週期的具體實現。apache
這個LifeCycle接口上面在講解Server和Service時其實已經有所接觸。Tomcat經過org.apache.catalina.LifeCycle接口統一接管Tomcat的生命週期,全部繼承自它的組件(即Component)都須要實現這個接口。
咱們先俯視看一看LifeCycle接口的定義。安全
根據上圖,咱們清晰看到上圖包含了4個生命週期的方法:
1. init
2. start
3. stop
4. destroy
這4個方法不用多解釋,很直觀,咱們前面也有所接觸。eclipse
同時,每一個方法又定義了幾個常量字符串,用於LifeCycleEvent事件的type屬性,用來描述各個狀態的變化。舉個例子,對於init週期,它包含before_init和 after_init兩個字符串,其餘相似。ide
它同時也定義了三個管理監聽器的方法,分別以下:
• addLifeCycleListener
• findLifeCycleListeners
• removeLifeCycleListener
顯而易見,它們用來增長、查找和刪除生命週期的監聽器。學習
最後定義了獲取當前狀態信息,用2個方法實現:
• getState
• getStateName
getState返回的是LifeCycleState,並且LifeCycleState是一個枚舉類型。以下this
public enum LifecycleState { NEW(false, null), INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT), INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT), STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT), STARTING(true, Lifecycle.START_EVENT), STARTED(true, Lifecycle.AFTER_START_EVENT), STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT), STOPPING(false, Lifecycle.STOP_EVENT), STOPPED(false, Lifecycle.AFTER_STOP_EVENT), DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT), DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT), FAILED(false, null);
咱們看到它列舉了Tomcat各個生命週期。spa
LifeCycleBase是實現了LifeCycle的抽象類,Tomcat的幾個生命週期的管理都交給它,因此弄清楚這個類的實現,基本上也就明白了Tomcat的生命週期了。線程
在LifeCycle接口裏,咱們提到的4個週期的方法以及3個監聽器的管理方法,最後還有2個獲取狀態信息的方法,咱們接下來逐一分析和了解。debug
方法initcode
public final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { setStateInternal(LifecycleState.INITIALIZING, null, false); initInternal(); setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.initFail", toString()); } }
先判斷當前狀態是否是NEW,若是不是拋出異常。由於init時,表明的是Tomcat的初始化,因此其狀態須要爲NEW的。接下來就是設置狀態爲LifecycleState.INITIALIZING,也就是正在初始化,而後調用initInternal開始初始化了,初始化完以後設置爲LifecycleState.INITIALIZED
這裏須要多說一下invalidTransition這個方法,由於後面不少地方都會用到它。
private void invalidTransition(String type) throws LifecycleException { String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state); throw new LifecycleException(msg); }
咱們看到invalidTransition方法其實沒作其餘事情,就是拋出了一個異常而已。
同時,也介紹一下setStateInternal這個方法,後面也用的較多。
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { if (log.isDebugEnabled()) { log.debug(sm.getString("lifecycleBase.setState", this, state)); } if (check) { // Must have been triggered by one of the abstract methods (assume // code in this class is correct) // null is never a valid state if (state == null) { invalidTransition("null"); // Unreachable code - here to stop eclipse complaining about // a possible NPE further down the method return; } // Any method can transition to failed // startInternal() permits STARTING_PREP to STARTING // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to // STOPPING 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))) { // No other transition permitted invalidTransition(state.name()); } } this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } }
變量check是傳進來的,是否要檢查。至於後面的邏輯註釋寫的比較清楚,不符合邏輯的狀態轉化都會報錯,很少解釋。
後面的fireLifeCycleEvent的代碼以下:
protected void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(this, type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); } }
也是很簡單,就是讓LifeCycle的事件監聽者觸發事件,至於如何去使用這些event,則是每一個監聽者本身的業務邏輯了。這也符合一向的代碼實現方法,若是有多個監聽器,而後逐一觸發這些監聽器,這實際上是事件監聽最基本的實現方法。
以上就是init的方法實現。
方法start
直接上代碼
public final synchronized void start() throws LifecycleException { if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStarted", toString())); } return; } if (state.equals(LifecycleState.NEW)) { init(); } else if (state.equals(LifecycleState.FAILED)) { stop(); } else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) { invalidTransition(Lifecycle.BEFORE_START_EVENT); } try { setStateInternal(LifecycleState.STARTING_PREP, null, false); startInternal(); if (state.equals(LifecycleState.FAILED)) { // This is a 'controlled' failure. The component put itself into the // FAILED state so call stop() to complete the clean-up. stop(); } else if (!state.equals(LifecycleState.STARTING)) { // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. invalidTransition(Lifecycle.AFTER_START_EVENT); } else { setStateInternal(LifecycleState.STARTED, null, false); } } catch (Throwable t) { // This is an 'uncontrolled' failure so put the component into the // FAILED state and throw an exception. handleSubClassException(t, "lifecycleBase.startFail", toString()); } }
第一步就是檢查狀態的合理性,若是已經在準備或者開始了,直接拋出已經開始的exception。若是是NEW的話,說明init這一步沒有作,那就初始化一下。
正式開始啓動了,首先須要將狀態設置爲LifecycleState.STARTING_PREP,接下調用startInternal開始啓動。執行完startInternal後驗證state,若是狀態不對,要麼中止,要麼拋出異常。
方法destroy
destroy其實調用的是stop方法。
方法stop
Stop方法
public final synchronized void stop() throws LifecycleException { if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStopped", toString())); } return; } if (state.equals(LifecycleState.NEW)) { state = LifecycleState.STOPPED; return; } if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.BEFORE_STOP_EVENT); } try { if (state.equals(LifecycleState.FAILED)) { // Don't transition to STOPPING_PREP as that would briefly mark the // component as available but do ensure the BEFORE_STOP_EVENT is // fired fireLifecycleEvent(BEFORE_STOP_EVENT, null); } else { setStateInternal(LifecycleState.STOPPING_PREP, null, false); } stopInternal(); // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.AFTER_STOP_EVENT); } setStateInternal(LifecycleState.STOPPED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.stopFail", toString()); } finally { if (this instanceof Lifecycle.SingleUse) { // Complete stop process first setStateInternal(LifecycleState.STOPPED, null, false); destroy(); } } }
首先,檢查一下當前狀態,若是當前狀態爲與STOP相關的幾個狀態,則拋出已經中止的異常。若是爲NEW,說明尚未初始化,直接將STOPPED的狀態賦值一下便可。若是狀態不是STARTED,是不能夠中止的,這個時候直接拋出異常。將觸發的event給監聽器和前面相似,很少作解釋。
前面介紹到LifeCycleBase有三個方法來管理監聽器:
• addLifeCycleListener
• findLifeCycleListeners
• removeLifeCycleListener
咱們看看它們的實現。
@Override public void addLifecycleListener(LifecycleListener listener) { lifecycleListeners.add(listener); } /** * {@inheritDoc} */ @Override public LifecycleListener[] findLifecycleListeners() { return lifecycleListeners.toArray(new LifecycleListener[0]); } /** * {@inheritDoc} */ @Override public void removeLifecycleListener(LifecycleListener listener) { lifecycleListeners.remove(listener); }
代碼比較簡單了,可是須要注意的是lifecycleListeners是一個CopyOnWriteArrayList。
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
關於CopyOnWriteArrayList,它繼承了ArrayList。咱們都知道ArrayList不是線程安全的,但CopyOnWriteArrayList則是線程安全的。
/** * Creates a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection of initially held elements * @throws NullPointerException if the specified collection is null */ public CopyOnWriteArrayList(Collection<? extends E> c) { Object[] elements; if (c.getClass() == CopyOnWriteArrayList.class) elements = ((CopyOnWriteArrayList<?>)c).getArray(); else { elements = c.toArray(); // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elements.getClass() != Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); } setArray(elements); }
咱們能夠看到代碼行
elements = c.toArray();
它實際上是Copy一份c,這種開銷是很大的。儘管開銷很大,可是當遍歷操做的數量大大超過可變操做的數量時,這種方法可能比其餘替代方法更有效。
同時,在add和remove時,咱們看到使用到ReentrantLock來保證線程安全。
CopyOnWriteArray比較適用於讀多修改少的情景。在Tomcat這裏,通常來講Listener都是在Server.xml,若是在想增長或刪除Listener,必須從新啓動Tomcat,在這種場景下,其實正好符合讀多寫少這種特徵。
public void add(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; if (index > len || index < 0) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+len); Object[] newElements; int numMoved = len - index; if (numMoved == 0) newElements = Arrays.copyOf(elements, len + 1); else { newElements = new Object[len + 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index, newElements, index + 1, numMoved); } newElements[index] = element; setArray(newElements); } finally { lock.unlock(); } } /** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). Returns the element that was removed from the list. * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(elements, index); int numMoved = len - index - 1; if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); else { Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements); } return oldValue; } finally { lock.unlock(); } }
獲取狀態
@Override public LifecycleState getState() { return state; } /** * {@inheritDoc} */ @Override public String getStateName() { return getState().toString(); }
代碼很是簡單,不介紹了。