Tomcat中组件的生命周期管理(一)
本文主要的目的是介绍了Catalina
中所有组件的生命周期的概念以及整个生命周期的架构图。
在之前的文章中介绍了tomcat整体的启动关闭流程,从流程中可以看出tomcat在启动和关闭的过程中涉及的组件相当之多,也可以看出tomcat是一个高度模块化的web容器。那么tomcat在启动关闭的时候是如何统一的管理所有的组件呢,之前在分析的时候也有所涉及,但是没有专门的去讲解,今天我们专门来看看这方面的相关作用原理。
Catalina中包含多个组件,在启动的时候会依次启动所有的组件,在关闭的时候会依次关闭所有的组件,从而做到管理生命周期目的。在Catalina中生命周期的概念被抽象为LifeCycle
接口,所有的需要Catalina管理的组件都必须实现LifeCycle
接口。当然并不是一个Lifecycle
接口就可以实现组件生命周期的目的,在Catalina中使用了很多相关的类,抽象类,接口来完成这件事情,我们可以先看下相关的类图。
Lifecycle
生命周期的顶层接口,在接口中定义了一些最基本的生命周期事件以及一些基础的方法。
/**
* The LifecycleEvent type for the "component after init" event.
*/
public static final String BEFORE_INIT_EVENT = "before_init";
/**
* The LifecycleEvent type for the "component after init" event.
*/
public static final String AFTER_INIT_EVENT = "after_init";
/**
* The LifecycleEvent type for the "component start" event.
*/
public static final String START_EVENT = "start";
......
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
通过源码可以看到,生命周期大致分为init
,start
,stop
,destroy
四步,每一步对应的事件有可能有 before事件 ,也有可能有 after事件。除此以外lifecycle
接口还定义了对 事件监听器 LifecycleListener
的一些基本操作,包含添加,查找 ,删除。
LifecycleEvent
Catalina使用类LifecycleEvent
来代表一个生命周期事件。
/**
* 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;
}
LifecycleEvent
的构造函数需要传递一个Lifecycle
实例,参数type
所有的类型都在Lifecycle
接口中定义的String
类型的常量,参数data
则是携带的一些参数。
LifecycleListener
生命周期的监听器,主要监听的是某个组件是否触发了哪个对应的生命周期事件。Lifecycle
接口定义了对LifecycleListener
的最基本的几个操作。LifecycleListener
一般是在组件初始化的时候添加到组件的内部,在内部只定义了一个lifecycleEvent
表示触发指定事件,如果需要对指定组件在指定生命周期事件的时候做一些事情,需要实现LifecycleListener
接口,并且复写lifecycleEvent
方法。
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
LifecycleState
lifecycleState
是一个枚举,用来表示Catalina中组件当前的生命周期状态,查看源码可以知道组件总共具有12种(有两种会在tomcat9.x废弃,当前版本为tomcat7.x)生命周期状态,如下:
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),
/**
* @deprecated Unused. Will be removed in Tomcat 9.0.x. The state transition
* checking in {@link org.apache.catalina.util.LifecycleBase}
* makes it impossible to use this state. The intended behaviour
* can be obtained by setting the state to
* {@link LifecycleState#FAILED} in
* <code>LifecycleBase.startInternal()</code>
*/
@Deprecated
MUST_STOP(true, null),
/**
* @deprecated Unused. Will be removed in Tomcat 9.0.x. The state transition
* checking in {@link org.apache.catalina.util.LifecycleBase}
* makes it impossible to use this state. The intended behaviour
* can be obtained by implementing {@link Lifecycle.SingleUse}.
*/
@Deprecated
MUST_DESTROY(false, null);
可以看出生命周期状态和Lifecycle
接口中定义的事件类息息相关。
LifecycleSupport
可以把这个类想想成一个工具类,这个类是实现组件触发生命周期监听器(LifecycleListener)的关键类,Catalina使用这个类完成了所有组件的关于LifecycleListener
的添加,查找,删除,触发。后面我们会重点分析其源码,可以先大致浏览下。
public final class LifecycleSupport {
/**
* Construct a new LifecycleSupport object associated with the specified
* Lifecycle component.
*
* @param lifecycle The Lifecycle component that will be the source
* of events that we fire
构造器需要传入一个lifecycle实例
*/
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
// ------------------------------成员变量
/**
* The source component for lifecycle events that we will fire.
*/
private Lifecycle lifecycle = null;
/**
* The set of registered LifecycleListeners for event notifications.
监听器 数组
*/
private LifecycleListener listeners[] = new LifecycleListener[0];
//用来同步的锁
private final Object listenersLock = new Object(); // Lock object for changes to listeners
/**
* 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;
}
}
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners() {
return listeners;
}
/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
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);
}
/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener) {
synchronized (listenersLock) {
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;
}
}
}
从源码中我们可以看到该类构造器需要传递一个Lifecycle
实例,内部成员变量包含一个LifecycleListener
数组,以及实现了Lifecycle
对应的添加,删除,查找方法,同时还有一个LifecycleListener
的触发方法,具体的源码我们稍后进行分析。
LifecycleBase
Catalina使用LifecycleBase
这个类来实现了所有关于生命周期的功能,包括了LifecycleListener
的相关功能,我们先来查看下源码
public abstract class LifecycleBase implements Lifecycle {
private static Log log = LogFactory.getLog(LifecycleBase.class);
private static StringManager sm =
StringManager.getManager("org.apache.catalina.util");
/**
* Used to handle firing lifecycle events.
* TODO: Consider merging LifecycleSupport into this class.
*/
private LifecycleSupport lifecycle = new LifecycleSupport(this);
/**
* The current state of the source component.
*/
private volatile LifecycleState state = LifecycleState.NEW;
/**
* {@inheritDoc}
*/
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
/**
* {@inheritDoc}
*/
@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
/**
* {@inheritDoc}
*/
@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
/**
* Allow sub classes to fire {@link Lifecycle} events.
*
* @param type Event type
* @param data Data associated with event.
*/
protected void fireLifecycleEvent(String type, Object data) {
lifecycle.fireLifecycleEvent(type, data);
}
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
setStateInternal(LifecycleState.INITIALIZING, null, false);
try {
initInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
setStateInternal(LifecycleState.INITIALIZED, null, false);
}
protected abstract void initInternal() throws LifecycleException;
/**
* {@inheritDoc}
*/
@Override
public final synchronized void start() throws LifecycleException {
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
return;
}
if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
setStateInternal(LifecycleState.STARTING_PREP, null, false);
try {
startInternal();
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
}
/**
* Sub-classes must ensure that the state is changed to
* {@link LifecycleState#STARTING} during the execution of this method.
* Changing state will trigger the {@link Lifecycle#START_EVENT} event.
*
* If a component fails to start it may either throw a
* {@link LifecycleException} which will cause it's parent to fail to start
* or it can place itself in the error state in which case {@link #stop()}
* will be called on the failed component but the parent component will
* continue to start normally.
*
* @throws LifecycleException
*/
protected abstract void startInternal() throws LifecycleException;
/**
* {@inheritDoc}
*/
@Override
public final synchronized void stop() throws LifecycleException {
if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
LifecycleState.STOPPED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
}
return;
}
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
}
if (state.equals(LifecycleState.FAILED)) {
// Don't transition to STOPPING_PREP as that would briefly mark the
// component as available but do ensure the BEFORE_STOP_EVENT is
// fired
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
try {
stopInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
} finally {
if (this instanceof Lifecycle.SingleUse) {
// Complete stop process first
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
return;
}
}
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.AFTER_STOP_EVENT);
}
setStateInternal(LifecycleState.STOPPED, null, false);
}
/**
* Sub-classes must ensure that the state is changed to
* {@link LifecycleState#STOPPING} during the execution of this method.
* Changing state will trigger the {@link Lifecycle#STOP_EVENT} event.
*
* @throws LifecycleException
*/
protected abstract void stopInternal() throws LifecycleException;
@Override
public final synchronized void destroy() throws LifecycleException {
if (LifecycleState.FAILED.equals(state)) {
try {
// Triggers clean-up
stop();
} catch (LifecycleException e) {
// Just log. Still want to destroy.
log.warn(sm.getString(
"lifecycleBase.destroyStopFail", toString()), e);
}
}
if (LifecycleState.DESTROYING.equals(state) ||
LifecycleState.DESTROYED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
} else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
// Rather than have every component that might need to call
// destroy() check for SingleUse, don't log an info message if
// multiple calls are made to destroy()
log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
}
return;
}
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
}
setStateInternal(LifecycleState.DESTROYING, null, false);
try {
destroyInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.destroyFail",toString()), t);
}
setStateInternal(LifecycleState.DESTROYED, null, false);
}
protected abstract void destroyInternal() throws LifecycleException;
/**
* {@inheritDoc}
*/
@Override
public LifecycleState getState() {
return state;
}
/**
* {@inheritDoc}
*/
@Override
public String getStateName() {
return getState().toString();
}
/**
* 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);
}
/**
* 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
* @param data The data to pass to the associated {@link Lifecycle} event
*/
protected synchronized void setState(LifecycleState state, Object data)
throws LifecycleException {
setStateInternal(state, data, true);
}
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);
}
}
private void invalidTransition(String type) throws LifecycleException {
String msg = sm.getString("lifecycleBase.invalidTransition", type,
toString(), state);
throw new LifecycleException(msg);
}
}
从源码上我们可以把LifecycleBase
类的功能分为两个部分。第一部分是是关于LifecycleListener
的相关功能,例如添加,删除,查找,触发相关事件,这部分功能都由LifecycleBase
内部的成员变量LifecycleSupport
完成。第二部分是关于接口Lifecycle
相关方法的实现。简单总结就是LifecycleBase
这个类用来实现关于生命周期的所有功能,其中分两部分,跟监听器有关系的功能由内部成员变量LifecycleBase
实例实现,另外一部分就是实现了Lifecycle
接口内部定义的所有方法。
通过上面的介绍我们大致了解了关于生命周期所有类的功能作用,可以发现最重要的两个类就是LifecycleSupport
和LifecycleBase
,下面的文章我们通过分析两个类的源码来搞懂相关功能的原理实现。