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
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接口内的注释就有详细的状态转换图。
3. 生命周期事件监听
对于存在状态的转换事件,对事件进行监听,并同时做点什么,这样大大增加了代码的扩展性,并满足了在一定的状态同时做点什么的需求。
一般来说,事件监听器需要三个参与者:
- 事件对象,用于封装事件的信息,在事件监听器接口的统一方法中作为参数使用,一般继承java. util.EventObject类。
- 事件源,触发事件的源头,不同的事件源会触发不同的事件类型。
- 事件监听器,负责监听事件源发出的事件,更确切地说,应该是每当发生事件时,事件源就会调用监听器的统一方法去处理,监听器一般实现java.util.EventListener接口。
todo
下一篇: tomcat启动流程分析
推荐阅读
-
【机器人学】机器人开源项目KDL源码学习:(6)笛卡尔空间轨迹规划、圆弧过渡、姿态插值、梯形速度、pathlength
-
tomcat 源码学习
-
tomcat 源码学习
-
Tomcat8源码分析系列-启动分析(一) Lifecycle
-
Tomcat源码学习(6)- Lifecycle
-
Tomcat 7源码学习笔记 -4 encoding的处理机制
-
Tomcat源码分析 (三)----- 生命周期机制 Lifecycle
-
Android architecture components学习笔记1-Lifecycle源码分析
-
jQuery源码学习(6)-Sizzle选择器(2)
-
Tomcat 7源码学习笔记 -6 encodeURL深度解析