Tomcat有很多组件,在Tomcat启动的同时,这些组件也应该跟着启动,在Tomcat要停止之前,这些组件需要有机会完成自己的收尾工作.
之前提过servlet的生命周期,从上一节我们知道一个Wrapper代表一个Servlet,一个Context可以有很多个Wrapper.当一个Context要停止,它会调用它的Wrapper的stop方法,Wrapper会调用servlet的destory方法.
一个组件只需实现org.apache.catalina.Lifecycle就可以管理自己的生命周期了。
看一下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; }start和 stop算是最重要的两个方法了, 父组件在start/stop时会调用它的子组件的start/stop方法,完成启动/停止。
Lifecycle里只有生命周期事件的名称,来看下它的实现:
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这个帮助类。
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是如何启动/停止它的子组件、子容器,绑定生命周期事件和监听器的呢。
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可以"一键"启动/停止所有组件。