本文接下来描述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 ( #改为@ )