Tomcat有不少組件,在Tomcat啓動的同時,這些組件也應該跟着啓動,在Tomcat要中止以前,這些組件須要有機會完成本身的收尾工做. java
以前提過servlet的生命週期,從上一節咱們知道一個Wrapper表明一個Servlet,一個Context能夠有不少個Wrapper.當一個Context要中止,它會調用它的Wrapper的stop方法,Wrapper會調用servlet的destory方法. apache
一個組件只需實現org.apache.catalina.Lifecycle就能夠管理本身的生命週期了。 數組
看一下Lifecycle的接口定義: app
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; }start和 stop算是最重要的兩個方法了, 父組件在start/stop時會調用它的子組件的start/stop方法,完成啓動/中止。
Lifecycle裏只有生命週期事件的名稱,來看下它的實現: this
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); } }再看下監聽器接口LifecycleListener :
public interface LifecycleListener { //當監聽器感興趣的事情發生時 調用該方法 public void lifecycleEvent(LifecycleEvent event); }
監聽器是怎麼樣註冊本身感興趣的事件呢?那就須要LifecycleSupport這個幫助類。 spa
public final class LifecycleSupport { public LifecycleSupport(Lifecycle lifecycle) { super(); this.lifecycle = lifecycle; } //引用一個實現了Lifecycle接口的Tomcat組件 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是如何啓動/中止它的子組件、子容器,綁定生命週期事件和監聽器的呢。 rest
public class SimpleContext implements Context, Pipeline, Lifecycle { //把SimpleContext本身註冊給幫助類 protected LifecycleSupport lifecycle = new LifecycleSupport(this); //委託幫助類處理監聽器 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"); lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); started = true; try { if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); //啓動子容器 Container Children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } //啓動pipeline中的value(包括baseValue) if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); //綁定事件監聽器 lifecycle.firelifecycleEvent(START_EVENT, null); } catch (Exception e) { e.printStackTrace(); } lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); } public void stop() throws LifecycleException { if (!started) throw new LifecycleException("SimpleContext has not been started"); lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null); lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; try { if (pipeline instanceof Lifecycle){ ((Lifecycle) pipeline).stop(); } 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(); } lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); }
Lifecycle接口定義了一個組件的生命週期,並提供一個優雅的方式向組件推送事件。
另外經過Lifecycle接口,Tomcat能夠"一鍵"啓動/中止全部組件。 code