分享

Tomcat7启动分析(五)Lifecycle机制和实现原理

 STRPS 2017-02-19

在上篇文章分析Tomcat7的各组件的init、start方法时经常会看到有一个setStateInternal方法的调用,在查看LifecycleBase类及其它各组件的源码时会在多处看到这个方法的调用,这篇文章就来说说这方法,以及与这个方法相关的Tomcat的Lifecycle机制和实现原理。

 

上篇文章里谈到Tomcat7的各组件的父类LifecycleBase类,该类实现了接口org.apache.catalina.Lifecycle,下面是这个接口里定义的常量和方法:


细心的读者会发现,上篇文章里提到的init和start方法实际上是在这个接口里面定义好的,也正因为有各组件最终都会实现这个接口作为前提条件,所以才能支持组件内部的initInternal、startInternal方法内对于子组件(组件里面嵌套的子组件都是以接口的形式定义的,但这些接口都会以Lifecycle作为父接口)的init和start方法的调用。通过这种方式,只要调用了最外层的Server组件的init和start方法,就可以将Tomcat内部的各级子组件初始化和启动起来。我叫这种方式为链式调用。实际上关于Tomcat的关闭机制也是通过这种方式一步步调用各层组件的stop方法的。这里不再展开叙述,留待读者自己研究研究吧。眨眼

 

Lifecycle接口中的这些字符串常量定义主要用于事件类型的定义,先按下不表,文章后面会提到。

 

重点看下面三个方法:

Java代码  收藏代码
  1. /** 
  2.  * Add a LifecycleEvent listener to this component. 
  3.  * 
  4.  * @param listener The listener to add 
  5.  */  
  6. public void addLifecycleListener(LifecycleListener listener);//给该组将添加一个监听器  
  7.   
  8.   
  9. /** 
  10.  * Get the life cycle listeners associated with this life cycle. If this 
  11.  * component has no listeners registered, a zero-length array is returned. 
  12.  */  
  13. public LifecycleListener[] findLifecycleListeners();//获取该组件所有已注册的监听器  
  14.   
  15.   
  16. /** 
  17.  * Remove a LifecycleEvent listener from this component. 
  18.  * 
  19.  * @param listener The listener to remove 
  20.  */  
  21. public void removeLifecycleListener(LifecycleListener listener);//删除该组件中的一个监听器  
/** * Add a LifecycleEvent listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener);//给该组将添加一个监听器 /** * Get the life cycle listeners associated with this life cycle. If this * component has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners();//获取该组件所有已注册的监听器 /** * Remove a LifecycleEvent listener from this component. * * @param listener The listener to remove */ public void removeLifecycleListener(LifecycleListener listener);//删除该组件中的一个监听器

这三个方法的作用在代码的注释里简要说明了一下。这三个方法涉及org.apache.catalina.LifecycleListener接口,那么就看下这个接口的定义:

Java代码  收藏代码
  1. public interface LifecycleListener {  
  2.   
  3.   
  4.     /** 
  5.      * Acknowledge the occurrence of the specified event. 
  6.      * 
  7.      * @param event LifecycleEvent that has occurred 
  8.      */  
  9.     public void lifecycleEvent(LifecycleEvent event);  
  10.   
  11.   
  12. }  
public interface LifecycleListener { /** * Acknowledge the occurrence of the specified event. * * @param event LifecycleEvent that has occurred */ public void lifecycleEvent(LifecycleEvent event); }

如此简单,只有一个方法,这个方法用作某个事件(org.apache.catalina.LifecycleEvent)产生时通知当前监听器的实现类,具体针对该事件如何处理由监听器实现类自己决定。

 

看下LifecycleEvent的实现:

Java代码  收藏代码
  1. public final class LifecycleEvent extends EventObject {  
  2.   
  3.     private static final long serialVersionUID = 1L;  
  4.   
  5.   
  6.     // ----------------------------------------------------------- Constructors  
  7.   
  8.     /** 
  9.      * Construct a new LifecycleEvent with the specified parameters. 
  10.      * 
  11.      * @param lifecycle Component on which this event occurred 
  12.      * @param type Event type (required) 
  13.      * @param data Event data (if any) 
  14.      */  
  15.     public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {  
  16.   
  17.         super(lifecycle);  
  18.         this.type = type;  
  19.         this.data = data;  
  20.     }  
  21.   
  22.   
  23.     // ----------------------------------------------------- Instance Variables  
  24.   
  25.   
  26.     /** 
  27.      * The event data associated with this event. 
  28.      */  
  29.     private Object data = null;  
  30.   
  31.   
  32.     /** 
  33.      * The event type this instance represents. 
  34.      */  
  35.     private String type = null;  
  36.   
  37.   
  38.     // ------------------------------------------------------------- Properties  
  39.   
  40.   
  41.     /** 
  42.      * Return the event data of this event. 
  43.      */  
  44.     public Object getData() {  
  45.   
  46.         return (this.data);  
  47.   
  48.     }  
  49.   
  50.   
  51.     /** 
  52.      * Return the Lifecycle on which this event occurred. 
  53.      */  
  54.     public Lifecycle getLifecycle() {  
  55.   
  56.         return (Lifecycle) getSource();  
  57.   
  58.     }  
  59.   
  60.   
  61.     /** 
  62.      * Return the event type of this event. 
  63.      */  
  64.     public String getType() {  
  65.   
  66.         return (this.type);  
  67.   
  68.     }  
  69.   
  70.   
  71. }  
public final class LifecycleEvent extends EventObject { private static final long serialVersionUID = 1L; // ----------------------------------------------------------- Constructors /** * Construct a new LifecycleEvent with the specified parameters. * * @param lifecycle Component on which this event occurred * @param type Event type (required) * @param data Event data (if any) */ public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super(lifecycle); this.type = type; this.data = data; } // ----------------------------------------------------- Instance Variables /** * The event data associated with this event. */ private Object data = null; /** * The event type this instance represents. */ private String type = null; // ------------------------------------------------------------- Properties /** * Return the event data of this event. */ public Object getData() { return (this.data); } /** * Return the Lifecycle on which this event occurred. */ public Lifecycle getLifecycle() { return (Lifecycle) getSource(); } /** * Return the event type of this event. */ public String getType() { return (this.type); } }

这个类也很简单,data和type作为类的内置实例变量,唯一特别是使用了jdk内置的java.util.EventObject作为父类来支持事件定义,这里在事件构造函数中将org.apache.catalina.Lifecycle类的实例lifecycle作为事件源,保存lifecycle对象的引用,并提供了getLifecycle方法返回这个引用。

 

那么Tomcat中是如何实现关于这些事件的监听以及通知的呢?

 

在本文开头提到的LifecycleBase类中第47行定义了一个实例变量lifecycle,正是通过该变量来注册组件上定义的各类监听器的。留心一下lifecycle这个实例变量,它并不是org.apache.catalina.Lifecycle类的实例,而是org.apache.catalina.util.LifecycleSupport类的实例。正是这个工具类提供了事件监听和事件通知的功能。

 

先看下实际代码中是如何给组件发布时间通知的,看下前面文章中曾经提到过的org.apache.catalina.core.StandardServer类的startInternal方法:

Java代码  收藏代码
  1. protected void startInternal() throws LifecycleException {  
  2.   
  3.     fireLifecycleEvent(CONFIGURE_START_EVENT, null);  
  4.     setState(LifecycleState.STARTING);  
  5.   
  6.     globalNamingResources.start();  
  7.       
  8.     // Start our defined Services  
  9.     synchronized (services) {  
  10.         for (int i = 0; i < services.length; i ) {  
  11.             services[i].start();  
  12.         }  
  13.     }  
  14. }  
protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (services) { for (int i = 0; i < services.length; i ) { services[i].start(); } } }

我们前面已经分析过第9到13行代码,这里看下第3行,它调用了父类org.apache.catalina.util.LifecycleBase里的fireLifecycleEvent方法,这里的CONFIGURE_START_EVENT就是本文最开始Lifecycle接口中定义的常量,这里表示发布了一个start配置事件。

 

org.apache.catalina.util.LifecycleBase类中的fireLifecycleEvent方法里调用的是org.apache.catalina.util.LifecycleSupport类fireLifecycleEvent方法,该方法代码如下:

Java代码  收藏代码
  1. public void fireLifecycleEvent(String type, Object data) {  
  2.   
  3.     LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);  
  4.     LifecycleListener interested[] = listeners;  
  5.     for (int i = 0; i < interested.length; i )  
  6.         interested[i].lifecycleEvent(event);  
  7.   
  8. }  
public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = listeners; for (int i = 0; i < interested.length; i ) interested[i].lifecycleEvent(event); }

这里通过传进来的两个参数构造一个LifecycleEvent对象,然后向注册到组件中的所有监听器发布这个新构造的事件对象。

 

这里有个疑问,到底什么时候向组件里注册监听器的呢?

 

还是以StandardServer举例,在前面讲Digester的使用时,org.apache.catalina.startup.Catalina类的createStartDigester方法有这么一段代码:

Java代码  收藏代码
  1. // Configure the actions we will be using  
  2. digester.addObjectCreate('Server',  
  3.                          'org.apache.catalina.core.StandardServer',  
  4.                          'className');  
  5. digester.addSetProperties('Server');  
  6. digester.addSetNext('Server',  
  7.                     'setServer',  
  8.                     'org.apache.catalina.Server');  
  9.   
  10. digester.addObjectCreate('Server/GlobalNamingResources',  
  11.                          'org.apache.catalina.deploy.NamingResources');  
  12. digester.addSetProperties('Server/GlobalNamingResources');  
  13. digester.addSetNext('Server/GlobalNamingResources',  
  14.                     'setGlobalNamingResources',  
  15.                     'org.apache.catalina.deploy.NamingResources');  
  16.   
  17. digester.addObjectCreate('Server/Listener',  
  18.                          null// MUST be specified in the element  
  19.                          'className');  
  20. digester.addSetProperties('Server/Listener');  
  21. digester.addSetNext('Server/Listener',  
  22.                     'addLifecycleListener',  
  23.                     'org.apache.catalina.LifecycleListener');  
// Configure the actions we will be using digester.addObjectCreate('Server', 'org.apache.catalina.core.StandardServer', 'className'); digester.addSetProperties('Server'); digester.addSetNext('Server', 'setServer', 'org.apache.catalina.Server'); digester.addObjectCreate('Server/GlobalNamingResources', 'org.apache.catalina.deploy.NamingResources'); digester.addSetProperties('Server/GlobalNamingResources'); digester.addSetNext('Server/GlobalNamingResources', 'setGlobalNamingResources', 'org.apache.catalina.deploy.NamingResources'); digester.addObjectCreate('Server/Listener', null, // MUST be specified in the element 'className'); digester.addSetProperties('Server/Listener'); digester.addSetNext('Server/Listener', 'addLifecycleListener', 'org.apache.catalina.LifecycleListener');

第17到24行,将调用org.apache.catalina.core.StandardServer类的addLifecycleListener方法,将根据server.xml中配置的Server节点下的Listener节点所定义的className属性构造对象实例,并作为addLifecycleListener方法的入参。所有的监听器都会实现上面提到的org.apache.catalina.LifecycleListener接口。Server节点下的Listener节点有好几个,这里以org.apache.catalina.core.JasperListener举例。

 

在构造完org.apache.catalina.core.JasperListener类的对象之后,调用addLifecycleListener方法,这个方法并没有直接在org.apache.catalina.core.StandardServer类中定义,而是在它的父类org.apache.catalina.util.LifecycleBase中:

Java代码  收藏代码
  1. @Override  
  2. public void addLifecycleListener(LifecycleListener listener) {  
  3.     lifecycle.addLifecycleListener(listener);  
  4. }  
@Override public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); }

这里调用的是前述的org.apache.catalina.util.LifecycleSupport类的addLifecycleListener方法:

Java代码  收藏代码
  1. /** 
  2.  * Add a lifecycle event listener to this component. 
  3.  * 
  4.  * @param listener The listener to add 
  5.  */  
  6. public void addLifecycleListener(LifecycleListener listener) {  
  7.   
  8.   synchronized (listenersLock) {  
  9.       LifecycleListener results[] =  
  10.         new LifecycleListener[listeners.length   1];  
  11.       for (int i = 0; i < listeners.length; i )  
  12.           results[i] = listeners[i];  
  13.       results[listeners.length] = listener;  
  14.       listeners = results;  
  15.   }  
  16.   
  17. }  
/** * Add a lifecycle event listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { synchronized (listenersLock) { 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; } }

LifecycleSupport作为一个工具类,内部保存了一个监听器对象实例数组,见该类的第68行:

Java代码  收藏代码
  1. /** 
  2.  * The set of registered LifecycleListeners for event notifications. 
  3.  */  
  4. private LifecycleListener listeners[] = new LifecycleListener[0];  
/** * The set of registered LifecycleListeners for event notifications. */ private LifecycleListener listeners[] = new LifecycleListener[0];

上面的addLifecycleListener方法内部实现的是同步给该数组增加一个监听器对象。

 

看到这里应该大体明白Tomcat中的Lifecycle是怎么回事了,总的来说就是通过一个工具类LifecycleSupport,调用该类的addLifecycleListener方法增加监听器,需要发布事件时还是调用该工具类的fireLifecycleEvent方法,将事件发布给组件上注册的所有监听器,由监听器内部实现来决定是否处理该事件。

 

以前面看到的一个监听器org.apache.catalina.core.JasperListener举例: 

Java代码  收藏代码
  1. public class JasperListener  
  2.     implements LifecycleListener {  
  3.   
  4.     private static final Log log = LogFactory.getLog(JasperListener.class);  
  5.   
  6.     /** 
  7.      * The string manager for this package. 
  8.      */  
  9.     protected static final StringManager sm =  
  10.         StringManager.getManager(Constants.Package);  
  11.   
  12.   
  13.     // ---------------------------------------------- LifecycleListener Methods  
  14.   
  15.   
  16.     /** 
  17.      * Primary entry point for startup and shutdown events. 
  18.      * 
  19.      * @param event The event that has occurred 
  20.      */  
  21.     @Override  
  22.     public void lifecycleEvent(LifecycleEvent event) {  
  23.   
  24.         if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {  
  25.             try {  
  26.                 // Set JSP factory  
  27.                 Class.forName('org.apache.jasper.compiler.JspRuntimeContext',  
  28.                               true,  
  29.                               this.getClass().getClassLoader());  
  30.             } catch (Throwable t) {  
  31.                 ExceptionUtils.handleThrowable(t);  
  32.                 // Should not occur, obviously  
  33.                 log.warn('Couldn't initialize Jasper', t);  
  34.             }  
  35.             // Another possibility is to do directly:  
  36.             // JspFactory.setDefaultFactory(new JspFactoryImpl());  
  37.         }  
  38.   
  39.     }  
  40.   
  41.   
  42. }  
public class JasperListener implements LifecycleListener { private static final Log log = LogFactory.getLog(JasperListener.class); /** * The string manager for this package. */ protected static final StringManager sm = StringManager.getManager(Constants.Package); // ---------------------------------------------- LifecycleListener Methods /** * Primary entry point for startup and shutdown events. * * @param event The event that has occurred */ @Override public void lifecycleEvent(LifecycleEvent event) { if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) { try { // Set JSP factory Class.forName('org.apache.jasper.compiler.JspRuntimeContext', true, this.getClass().getClassLoader()); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); // Should not occur, obviously log.warn('Couldn't initialize Jasper', t); } // Another possibility is to do directly: // JspFactory.setDefaultFactory(new JspFactoryImpl()); } } }

重点关注来自接口的lifecycleEvent方法的实现,可以看到这个监听器只关心事件类型为BEFORE_INIT_EVENT的事件,如果发布了该事件,才会做后续处理(这里会产生一个org.apache.jasper.compiler.JspRuntimeContext对象)。

 

Lifecycle相关类UML关系图:


 

如果对设计模式比较熟悉的话会发现Tomcat的Lifecycle使用的是观察者模式:LifecycleListener代表的是抽象观察者,它定义一个lifecycleEvent方法,而实现该接口的监听器是作为具体的观察者。Lifecycle 接口代表的是抽象主题,它定义了管理观察者的方法和它要所做的其它方法。而各组件代表的是具体主题,它实现了抽象主题的所有方法。通常会由具体主题保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知。Tomcat对这种模式做了改进,增加了另外两个工具类:LifecycleSupport、LifecycleEvent,它们作为辅助类扩展了观察者的功能。LifecycleEvent中定义了事件类别,不同的事件在具体观察者中可区别处理,更加灵活。LifecycleSupport 类代理了所有具体主题对观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改 LifecycleSupport 类就可以了,不需要去修改所有具体主题,因为所有具体主题的对观察者的操作都被代理给 LifecycleSupport 类了。

 

事件的发布使用的是推模式,即每发布一个事件都会通知主题的所有具体观察者,由各观察者再来决定是否需要对该事件进行后续处理。

 

下面再来看看本文一开头所说的setStateInternal方法,以org.apache.catalina.core.StandardServer类为例,上面看到的startInternal方法中第4行:setState(LifecycleState.STARTING);

它调用了父类org.apache.catalina.util.LifecycleBase中的setState方法:

Java代码  收藏代码
  1. /** 
  2.  * Provides a mechanism for sub-classes to update the component state. 
  3.  * Calling this method will automatically fire any associated 
  4.  * {@link Lifecycle} event. It will also check that any attempted state 
  5.  * transition is valid for a sub-class. 
  6.  *  
  7.  * @param state The new state for this component 
  8.  */  
  9. protected synchronized void setState(LifecycleState state)  
  10.         throws LifecycleException {  
  11.     setStateInternal(state, nulltrue);  
  12. }  
/** * Provides a mechanism for sub-classes to update the component state. * Calling this method will automatically fire any associated * {@link Lifecycle} event. It will also check that any attempted state * transition is valid for a sub-class. * * @param state The new state for this component */ protected synchronized void setState(LifecycleState state) throws LifecycleException { setStateInternal(state, null, true); }

在这个类里面调用本类的一个同步方法setStateInternal:

Java代码  收藏代码
  1. private synchronized void setStateInternal(LifecycleState state,  
  2.         Object data, boolean check) throws LifecycleException {  
  3.       
  4.     if (log.isDebugEnabled()) {  
  5.         log.debug(sm.getString('lifecycleBase.setState'this, state));  
  6.     }  
  7.       
  8.     if (check) {  
  9.         // Must have been triggered by one of the abstract methods (assume  
  10.         // code in this class is correct)  
  11.         // null is never a valid state  
  12.         if (state == null) {  
  13.             invalidTransition('null');  
  14.             // Unreachable code - here to stop eclipse complaining about  
  15.             // a possible NPE further down the method  
  16.             return;  
  17.         }  
  18.           
  19.         // Any method can transition to failed  
  20.         // startInternal() permits STARTING_PREP to STARTING  
  21.         // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to  
  22.         // STOPPING  
  23.         if (!(state == LifecycleState.FAILED ||  
  24.                 (this.state == LifecycleState.STARTING_PREP &&  
  25.                         state == LifecycleState.STARTING) ||  
  26.                 (this.state == LifecycleState.STOPPING_PREP &&  
  27.                         state == LifecycleState.STOPPING) ||  
  28.                 (this.state == LifecycleState.FAILED &&  
  29.                         state == LifecycleState.STOPPING))) {  
  30.             // No other transition permitted  
  31.             invalidTransition(state.name());  
  32.         }  
  33.     }  
  34.       
  35.     this.state = state;  
  36.     String lifecycleEvent = state.getLifecycleEvent();  
  37.     if (lifecycleEvent != null) {  
  38.         fireLifecycleEvent(lifecycleEvent, data);  
  39.     }  
  40. }  
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); } }

重点关注第35到39行,第35行将入参LifecycleState实例赋值给本类中的实例变量保存起来,第36行取出LifecycleState实例的LifecycleEvent事件,如果该事件非空,则调用fireLifecycleEvent方法发布该事件。

 

既然看到了LifecycleState类,就看下LifecycleState类的定义: 

Java代码  收藏代码
  1. public enum LifecycleState {  
  2.     NEW(falsenull),  
  3.     INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),  
  4.     INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),  
  5.     STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),  
  6.     STARTING(true, Lifecycle.START_EVENT),  
  7.     STARTED(true, Lifecycle.AFTER_START_EVENT),  
  8.     STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),  
  9.     STOPPING(false, Lifecycle.STOP_EVENT),  
  10.     STOPPED(false, Lifecycle.AFTER_STOP_EVENT),  
  11.     DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),  
  12.     DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),  
  13.     FAILED(falsenull),  
  14.     MUST_STOP(truenull),  
  15.     MUST_DESTROY(falsenull);  
  16.   
  17.     private final boolean available;  
  18.     private final String lifecycleEvent;  
  19.   
  20.     private LifecycleState(boolean available, String lifecycleEvent) {  
  21.         this.available = available;  
  22.         this.lifecycleEvent = lifecycleEvent;  
  23.     }  
  24.   
  25.     /** 
  26.      * May the public methods other than property getters/setters and lifecycle 
  27.      * methods be called for a component in this state? It returns 
  28.      * <code>true</code> for any component in any of the following states: 
  29.      * <ul> 
  30.      * <li>{@link #STARTING}</li> 
  31.      * <li>{@link #STARTED}</li> 
  32.      * <li>{@link #STOPPING_PREP}</li> 
  33.      * <li>{@link #MUST_STOP}</li> 
  34.      * </ul> 
  35.      */  
  36.     public boolean isAvailable() {  
  37.         return available;  
  38.     }  
  39.   
  40.     /** 
  41.      * 
  42.      */  
  43.     public String getLifecycleEvent() {  
  44.         return lifecycleEvent;  
  45.     }  
  46. }  
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), MUST_STOP(true, null), MUST_DESTROY(false, null); private final boolean available; private final String lifecycleEvent; private LifecycleState(boolean available, String lifecycleEvent) { this.available = available; this.lifecycleEvent = lifecycleEvent; } /** * May the public methods other than property getters/setters and lifecycle * methods be called for a component in this state? It returns * <code>true</code> for any component in any of the following states: * <ul> * <li>{@link #STARTING}</li> * <li>{@link #STARTED}</li> * <li>{@link #STOPPING_PREP}</li> * <li>{@link #MUST_STOP}</li> * </ul> */ public boolean isAvailable() { return available; } /** * */ public String getLifecycleEvent() { return lifecycleEvent; } }

这个类在之前的Tomcat4和Tomcat5中都没有看到,可能是Tomcat7里面新定义的吧,就是一个枚举,内嵌了两个实例变量,一个布尔值表示是否可用,一个字符串表示是事件类型,看已经定义的枚举值里面发现这个字符串要么不设值,要么就是Lifecycle类中定义好的字符串常量。这个类实际上就是对Lifecycle类中定义好的字符串常量做了另外一层封装。

 

再说回开头在各组件代码中经常会看到的setStateInternal方法的调用,实际上就是向该组件中已注册的监听器发布一个事件。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多