在继续Tomcat启动过程源码分析之前,我们先回顾一下Tomcat的生命周期,查看LifeCycle.java类的注释:
/**
* Common interface for component life cycle methods. Catalina components
* may implement this interface (as well as the appropriate interface(s) for
* the functionality they support) in order to provide a consistent mechanism
* to start and stop the component.
* <br>
* The valid state transitions for components that support {@link Lifecycle}
* are:
* <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() |
* ----»-----------------------------»------------------------------
*
* Any state can transition to FAILED.
*
* Calling start() while a component is in states STARTING_PREP, STARTING or
* STARTED has no effect.
*
* Calling start() while a component is in state NEW will cause init() to be
* called immediately after the start() method is entered.
*
* Calling stop() while a component is in states STOPPING_PREP, STOPPING or
* STOPPED has no effect.
*
* Calling stop() while a component is in state NEW transitions the component
* to STOPPED. This is typically encountered when a component fails to start and
* does not start all its sub-components. When the component is stopped, it will
* try to stop all sub-components - even those it didn't start.
*
* Attempting any other transition will throw {@link LifecycleException}.
*
* </pre>
* The {@link LifecycleEvent}s fired during state changes are defined in the
* methods that trigger the changed. No {@link LifecycleEvent}s are fired if the
* attempted transition is not valid.
*
* @author Craig R. McClanahan
*/
在上一篇文章中,我们提到LifecycleBase抽象类中的生命周期的各个阶段,会把生命周期事件通知给注册的监听器,在LifeCycleBase.fireLifecycleEvent中体现。那么监听器又是如何接受事件的呢?其实早在Catalina.createStartDigester()中,各个容器的生命周期被注册了最基本的监听器,即实现了LifecycleListener接口的监听器。
默认在Server.xml中注册监听器列表如下:
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
这里整理createStartDigester()中除去Server.xml注册基本的生命周期监听器之外,还额外注册若干重要监听器:
- StandardEngine:EngineConfig 用于打印Engine启动和停止日志;
- StandardHost:HostConfig 重要监听器,后详;
- StandardContext:ContextConfig 重要监听器,后详;
在创建的过程中,各层级的容器也会显示调用LifecycleBase.addLifecycleListener(LifecycleListener listener)方法。在发生了生命周期事件后,遍历所有注册的监听器,调用生命周期监听器的接口方法lifecycleEvent()。
以EngineHost为例:
/**
* Process the START event for an associated Engine.
*
* @param event The lifecycle event that has occurred
*/
@Override
public void lifecycleEvent(LifecycleEvent event) {
// Identify the engine we are associated with
try {
engine = (Engine) event.getLifecycle();
} catch (ClassCastException e) {
log.error(sm.getString("engineConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.START_EVENT))
start();
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
发生了Lifecycle.START_EVENT事件,调用自身start()方法;发生了Lifecycle.STOP_EVENT事件,调用自身的stop()方法。
也就是说,各容器在发出生命周期事件的消息时,其注册的每个监听器会对这个事件进行轮询响应。