欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Tomcat源码学习(6)- Lifecycle

程序员文章站 2022-07-14 10:46:48
...

1. Lifecycle接口

为了方便管理Tomcat众多组件的启动, 销毁,Tomcat抽象出一层LifeCycle接口来作为解决方案。

/**
 *组件生命周期方法的公共接口。卡特琳娜组件
*可以实现此接口(以及适用于他们支持的功能),以提供一致的机制
*启动和停止组件。

*支持{@link生命周期}的组件的有效状态转换
*:这图很重要哦
 * <pre>
 *            start()
 *  -----------------------------
 *  |                           |
 *  | init()                    |
 * NEW -»-- INITIALIZING        |
 * | |           |              |     ------------------«-----------------------
 * | |           |auto          |     |                                        |
 * | |          \|/    start() \|/   \|/     auto          auto         stop() |
 * | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
 * | |         |                                                            |  |
 * | |destroy()|                                                            |  |
 * | --»-----«--    ------------------------«--------------------------------  ^
 * |     |          |                                                          |
 * |     |         \|/          auto                 auto              start() |
 * |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
 * |    \|/                               ^                     |  ^
 * |     |               stop()           |                     |  |
 * |     |       --------------------------                     |  |
 * |     |       |                                              |  |
 * |     |       |    destroy()                       destroy() |  |
 * |     |    FAILED ----»------ DESTROYING ---«-----------------  |
 * |     |                        ^     |                          |
 * |     |     destroy()          |     |auto                      |
 * |     --------»-----------------    \|/                         |
 * |                                 DESTROYED                     |
 * |                                                               |
 * |                            stop()                             |
 * ----»-----------------------------»------------------------------
 *
*任何状态都可以转换为失败。
 *
*当组件处于STARTING_PREP、start或状态时调用start()
*启动没有效果。
 *
*当组件处于NEW状态时调用start()将导致init()为
*在进入start()方法后立即调用。
 *
*当组件处于STOPPING_PREP、stop或状态时调用stop()
*停止没有效果。
 *
*在组件处于状态时调用stop()
*停了下来。这通常在组件启动失败时遇到
*不会启动所有子组件。当组件停止时,它会停止
*尝试停止所有子组件-即使那些没有启动。
*
*尝试任何其他转换将抛出{@link LifecycleException}。
 *

属性中定义状态更改期间触发的{@link LifecycleEvent}
*触发改变的方法。没有{@link LifecycleEvent}被触发,如果
*尝试转换无效。
 */
public interface Lifecycle {


    // ----------------------------------------------------- 显化常数


    /**
     * “init之前的组件”事件的LifecycleEvent类型。
     */
    public static final String BEFORE_INIT_EVENT = "before_init";


    /**
     * “init之后的组件”事件的LifecycleEvent类型。
     */
    public static final String AFTER_INIT_EVENT = "after_init";


    /**
     * “组件启动”事件的LifecycleEvent类型。
     */
    public static final String START_EVENT = "start";


    /**
     * “启动前组件”事件的LifecycleEvent类型。
     */
    public static final String BEFORE_START_EVENT = "before_start";


    /**
     * “启动后组件”事件的LifecycleEvent类型。
     */
    public static final String AFTER_START_EVENT = "after_start";


    /**
     * “组件停止”事件的LifecycleEvent类型。
     */
    public static final String STOP_EVENT = "stop";


    /**
     * “停止前组件”事件的LifecycleEvent类型。
     */
    public static final String BEFORE_STOP_EVENT = "before_stop";


    /**
     * “停止后组件”事件的LifecycleEvent类型。
     */
    public static final String AFTER_STOP_EVENT = "after_stop";


    /**
     * “组件销毁后”事件的LifecycleEvent类型。
     */
    public static final String AFTER_DESTROY_EVENT = "after_destroy";


    /**
     * “销毁前组件”事件的LifecycleEvent类型。
     */
    public static final String BEFORE_DESTROY_EVENT = "before_destroy";


    /**
     * “周期”事件的LifecycleEvent类型。
     */
    public static final String PERIODIC_EVENT = "periodic";


    /**
   *“configure_start”事件的LifecycleEvent类型。使用这些
*使用独立组件执行配置和
*在需要进行配置时需要发出信号——通常是在配置完成后
* {@link #BEFORE_START_EVENT}和之前的{@link #START_EVENT}。
     */
    public static final String CONFIGURE_START_EVENT = "configure_start";


    /**
   *“configure_stop”事件的LifecycleEvent类型。使用这些
	*使用独立组件执行配置和
	*需要发出信号时,应执行解除配置-通常在之后
	* {@link #AFTER_STOP_EVENT}和之前的{@link #AFTER_STOP_EVENT}。
	    */
    public static final String CONFIGURE_STOP_EVENT = "configure_stop";


    // --------------------------------------------------------- Public Methods


    /**
   添加一个LifecycleEvent监听器到这个组件。
     *
     * @param listener The listener to add
     */
    public void addLifecycleListener(LifecycleListener listener);


    /**
    获取与此生命周期关联的生命周期侦听器。
	*
	返回一个数组,其中包含与之关联的生命周期监听器
	*生命周期。如果该组件没有注册侦听器,则调用
	*返回零长度数组。
     */
    public LifecycleListener[] findLifecycleListeners();


    /**
	  从这个组件中移除一个LifecycleEvent监听器。
     *
     * @param listener The listener to remove
     */
    public void removeLifecycleListener(LifecycleListener listener);


    /**
    *准备启动组件。此方法应该执行任何操作
	*初始化需要post对象创建。以下
 	* {@link LifecycleEvent}将按照以下顺序触发:
     * <ol>
     *   <li>INIT_EVENT:在组件成功完成时
     *                   initialization.</li>
     * </ol>
     *
     * @exception 如果该组件检测到致命错误,则使用LifecycleException
     * 这将阻止该组件被使用
     */
    public void init() throws LifecycleException;

    /**
    *准备开始积极使用公共方法,而不是
	*此组件的属性getter /setter和生命周期方法。这
	方法应该被调用之前的任何公共方法
	*此组件的属性getter /setter和生命周期方法是
	*利用。下面的{@link LifecycleEvent}将在
	*以下顺序 :
     * <ol>
     *   <li>BEFORE_START_EVENT: At the beginning of the method. It is as this
     *                           point the state transitions to
     *                           {@link LifecycleState#STARTING_PREP}.</li>
     *   <li>START_EVENT: During the method once it is safe to call start() for
     *                    any child components. It is at this point that the
     *                    state transitions to {@link LifecycleState#STARTING}
     *                    and that the public methods other than property
     *                    getters/setters and life cycle methods may be
     *                    used.</li>
     *   <li>AFTER_START_EVENT: At the end of the method, immediately before it
     *                          returns. It is at this point that the state
     *                          transitions to {@link LifecycleState#STARTED}.
     *                          </li>
     * </ol>
     *
     * @exception 如果该组件检测到致命错误,则使用LifecycleException
*防止该组件被使用
     */
    public void start() throws LifecycleException;


    /**
    优雅地终止公共方法的使用
	*此组件的属性getter /setter和生命周期方法。一次
	* STOP_EVENT被触发,公共方法而不是属性
	*不应该使用getter /setter和生命周期方法。以下
	* {@link LifecycleEvent}将按照以下顺序触发:
     * <ol>
     *   <li>BEFORE_STOP_EVENT: At the beginning of the method. It is at this
     *                          point that the state transitions to
     *                          {@link LifecycleState#STOPPING_PREP}.</li>
     *   <li>STOP_EVENT: During the method once it is safe to call stop() for
     *                   any child components. It is at this point that the
     *                   state transitions to {@link LifecycleState#STOPPING}
     *                   and that the public methods other than property
     *                   getters/setters and life cycle methods may no longer be
     *                   used.</li>
     *   <li>AFTER_STOP_EVENT: At the end of the method, immediately before it
     *                         returns. It is at this point that the state
     *                         transitions to {@link LifecycleState#STOPPED}.
     *                         </li>
     * </ol>
     *
    *注意,如果从{@link LifecycleState#转换失败},那么
	*上面的三个事件将被触发,但是组件将转换
	*直接从{@link LifecycleState#FAILED}到
	* {@link LifecycleState# stop},绕过
	* {@link LifecycleState # STOPPING_PREP}
	*
	* @exception LifecycleException如果这个组件检测到一个致命错误
	那件事需要报告
     */
    public void stop() throws LifecycleException;

    /**
    *准备丢弃物品。下面的{@link LifecycleEvent}将会
	*按以下顺序被解雇:
     * <ol>
     *   <li>DESTROY_EVENT: On the successful completion of component
     *                      destruction.</li>
     * </ol>
     *
     * @exception 如果该组件检测到致命错误,则使用LifecycleException
*防止该组件被使用
     */
    public void destroy() throws LifecycleException;


    /**
   获取源组件的当前状态。
     *
     * @return 源组件的当前状态。
     */
    public LifecycleState getState();


    /**
   获取当前组件状态的文本表示。有用的
	JMX的*。这个字符串的格式可能在点释放和点释放之间有所不同
	*不应该被用来确定组件的状态。来确定
	*组件状态,使用{@link #getState()}。
     *
     * @return The name of the current component state.
     */
    public String getStateName();


    /**
    *标记接口,用来指示该实例只能被使用
	*一次。在支持此接口的实例上调用{@link #stop()}
	*将在{@link #stop()}之后自动调用{@link #destroy()}
	*完成。
     */
    public interface SingleUse {
    }
}

Tomcat各个核心的组件有包含与被包含的关系,那么,可以通过父容器启动它的子容器,这样只要启动根容器,即可把其他所有容器都启动,达到统一启动、停止、关闭的效果。

从上面的源码可以看出:
Lifecycle其实就定义了一些状态常量和几个方法,这里主要看init、start、stop三个方法,所有需要被生命周期管理的容器都要实现这个接口,并且各自被父容器的相应方法调用。例如,在初始化阶段,根容器Server组件会调用init方法,而在init方法里会调用它的子容器Service组件的init方法,以此类推。

例如:org.apache.catalina.core.StandardServer#initInternal
Tomcat源码学习(6)- Lifecycle

2. 状态转化

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);

    private final boolean available;
    private final String lifecycleEvent;

    private LifecycleState(boolean available, String lifecycleEvent) {
        this.available = available;
        this.lifecycleEvent = lifecycleEvent;
    }

    /**
    *可能除了属性的getter /setter和生命周期之外的公共方法
	*方法被调用的组件在这种状态?它返回
	* true适用于任何处于以下状态的组件:
     * <ul>
     * <li>{@link #STARTING}</li>
     * <li>{@link #STARTED}</li>
     * <li>{@link #STOPPING_PREP}</li>
     * </ul>
     *
     * @return <code>true</code> 如果组件可用,
     *         otherwise false
     * 
	 */
    public boolean isAvailable() {
        return available;
    }

    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

其次,在LifeCycle接口内的注释就有详细的状态转换图。
Tomcat源码学习(6)- Lifecycle

3. 生命周期事件监听

对于存在状态的转换事件,对事件进行监听,并同时做点什么,这样大大增加了代码的扩展性,并满足了在一定的状态同时做点什么的需求。
一般来说,事件监听器需要三个参与者:

  • 事件对象,用于封装事件的信息,在事件监听器接口的统一方法中作为参数使用,一般继承java. util.EventObject类。
  • 事件源,触发事件的源头,不同的事件源会触发不同的事件类型。
  • 事件监听器,负责监听事件源发出的事件,更确切地说,应该是每当发生事件时,事件源就会调用监听器的统一方法去处理,监听器一般实现java.util.EventListener接口。

todo

相关标签: 源码