本文接下來描述servlet容器是怎樣管理其相關組件的生命周期的,首先本人描述一下事件監聽模式,也可以稱為觀察者模式,該模式分為以下角色
即抽象主題角色 具體主題角色 抽象觀察者角色及具體觀察者角色,通常在主題角色里面維持一個觀察者角色的聚集,并定義了對觀察者角色的添加和刪除方法;在主題角色事件發生時,通過迭代向這些觀察者角色發布事件。
在tomcat容器中,管理其相關組件的生命周期即是基于事件監聽模式實現的,相關接口和類為org.apache.catalina.Lifecycle接口、org.apache.catalina.LifecycleListener接口、org.apache.catalina.LifecycleEvent類
org.apache.catalina.Lifecycle接口定義如下
public interface Lifecycle { 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 void addLifecycleListener(LifecycleListener listener); public LifecycleListener[] findLifecycleListeners(); public void removeLifecycleListener(LifecycleListener listener); public void start() throws LifecycleException; public void stop() throws LifecycleException; }
上面的六個靜態字符串代表六種類型的事件,接著的三個方法addLifecycleListener()、 findLifecycleListeners()、removeLifecycleListener()為與事件監聽器相關的,最后的兩個方法start()和stop()為啟動與關閉操作,組件必須提供這兩種方法的實現,供其父組件調用。
org.apache.catalina.LifecycleEvent類用于傳遞事件及攜帶事件數據
public final class LifecycleEvent extends EventObject { public LifecycleEvent(Lifecycle lifecycle, String type) { this (lifecycle, type, null ); } public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super (lifecycle); this .lifecycle = lifecycle; this .type = type; this .data = data; } private Object data = null ; private Lifecycle lifecycle = null ; private String type = null ; public Object getData() { return ( this .data); } public Lifecycle getLifecycle() { return ( this .lifecycle); } public String getType() { return ( this .type); } }
org.apache.catalina.LifecycleListener為監聽器接口
public interface LifecycleListener { /** * Acknowledge the occurrence of the specified event. * * @param event LifecycleEvent that has occurred */ public void lifecycleEvent(LifecycleEvent event); }
通常實現了Lifecycle接口并且對某個事件注冊了監聽器的組件必須提供 Lifecycle接口中三個與監聽器相關方法(分別為addLifecycleListener()、 findLifecycleListeners()、removeLifecycleListener())的實現,然后該組件需要將所有注冊的監聽器存儲到數組、ArrayList或者其他類似的對象中;tomcat容器提供了一個工具類org.apache.catalina.util.LifecycleSupport來幫助組件管理監聽器,并觸發相應的生命周期事件。
public final class LifecycleSupport { public LifecycleSupport(Lifecycle lifecycle) { super (); this .lifecycle = lifecycle; } private Lifecycle lifecycle = null ; private LifecycleListener listeners[] = new LifecycleListener[0 ]; public void addLifecycleListener(LifecycleListener listener) { synchronized (listeners) { LifecycleListener results[] = new LifecycleListener[listeners.length + 1 ]; for ( int i = 0; i < listeners.length; i++ ) results[i] = listeners[i]; results[listeners.length] = listener; listeners = results; } } public LifecycleListener[] findLifecycleListeners() { return listeners; } public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = null ; synchronized (listeners) { interested = (LifecycleListener[]) listeners.clone(); } for ( int i = 0; i < interested.length; i++ ) interested[i].lifecycleEvent(event); } public void removeLifecycleListener(LifecycleListener listener) { synchronized (listeners) { int n = -1 ; for ( int i = 0; i < listeners.length; i++ ) { if (listeners[i] == listener) { n = i; break ; } } if (n < 0 ) return ; LifecycleListener results[] = new LifecycleListener[listeners.length - 1 ]; int j = 0 ; for ( int i = 0; i < listeners.length; i++ ) { if (i != n) results[j ++] = listeners[i]; } listeners = results; } } }
下面我們來看Context容器(SimpleContext實例)是怎么實現生命周期管理及觸發監聽器事件的,關鍵代碼如下
public class SimpleContext implements Context, Pipeline, Lifecycle { protected LifecycleSupport lifecycle = new LifecycleSupport( this ); // implementation of the Lifecycle interface's methods public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } public LifecycleListener[] findLifecycleListeners() { return null ; } public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } public synchronized void start() throws LifecycleException { if (started) throw new LifecycleException("SimpleContext has already started" ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null ); started = true ; try { // Start our subordinate components, if any if ((loader != null ) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); // Start our child containers, if any Container children[] = findChildren(); for ( int i = 0; i < children.length; i++ ) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } // Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null ); } catch (Exception e) { e.printStackTrace(); } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null ); } public void stop() throws LifecycleException { if (! started) throw new LifecycleException("SimpleContext has not been started" ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null ); lifecycle.fireLifecycleEvent(STOP_EVENT, null ); started = false ; try { // Stop the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).stop(); } // Stop our child containers, if any Container children[] = findChildren(); for ( int i = 0; i < children.length; i++ ) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).stop(); } if ((loader != null ) && (loader instanceof Lifecycle)) { ((Lifecycle) loader).stop(); } } catch (Exception e) { e.printStackTrace(); } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null ); } }
Context容器實例持有對LifecycleSupport lifecycle = new LifecycleSupport(this)的引用,與事件監聽器相關方法均為操作該實例的相應方法
在其與生命周期相關方法start()和stop()方法里面,分別調用相關組件的生命周期方法,并采用LifecycleSupport lifecycle引用發布事件
一個簡單的監聽器實現如下:
public class SimpleContextLifecycleListener implements LifecycleListener { public void lifecycleEvent(LifecycleEvent event) { Lifecycle lifecycle = event.getLifecycle(); System.out.println( "SimpleContextLifecycleListener's event " + event.getType().toString()); if (Lifecycle.START_EVENT.equals(event.getType())) { System.out.println( "Starting context." ); } else if (Lifecycle.STOP_EVENT.equals(event.getType())) { System.out.println( "Stopping context." ); } } }
子容器wrapper實例(SimpleWrapper),同樣實現了Lifecycle接口,其相關實現與Context容器類似
public class SimpleWrapper implements Wrapper, Pipeline, Lifecycle { protected LifecycleSupport lifecycle = new LifecycleSupport( this ); // implementation of the Lifecycle interface's methods public void addLifecycleListener(LifecycleListener listener) { } public LifecycleListener[] findLifecycleListeners() { return null ; } public void removeLifecycleListener(LifecycleListener listener) { } public synchronized void start() throws LifecycleException { System.out.println( "Starting Wrapper " + name); if (started) throw new LifecycleException("Wrapper already started" ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null ); started = true ; // Start our subordinate components, if any if ((loader != null ) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null ); } public void stop() throws LifecycleException { System.out.println( "Stopping wrapper " + name); // Shut down our servlet instance (if it has been initialized) try { instance.destroy(); } catch (Throwable t) { } instance = null ; if (! started) throw new LifecycleException("Wrapper " + name + " not started" ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null ); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(STOP_EVENT, null ); started = false ; // Stop the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).stop(); } // Stop our subordinate components, if any if ((loader != null ) && (loader instanceof Lifecycle)) { ((Lifecycle) loader).stop(); } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null ); } }
其他相關組件的相關實現不再贅述
---------------------------------------------------------------------------?
本系列How Tomcat Works系本人原創?
轉載請注明出處 博客園 刺猬的溫馴?
本人郵箱: ? chenying998179 # 163.com ( #改為@ )
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
