Tomcat详解(2)---Tomcat 的生命周期管理

时间:2021-01-01 08:59:50

2 Tomcat 的生命周期管理

2.1 Lifecycle 接口

 Tomcat 通过org.apache.catalina.Lifecycle 接口统一管理生命周期,所有有生命周期的组件都要实现Lifecycle 接口。Lifecycle 接口一共做了4 件事:

  • 定义了13 个String 类型常量, 用于LifecycleEvent 事件的type属性中,作用是区分组件发出的LifecycleEvent 事件时的状态(如初始化前、启动前、启动中等) 。这种设计方式可以让多种状态都发送同一种类型的事件(LifecycleEvent )然后用其中的一个属性来区分状态而不用定义多种事件。
  • 定义了三个管理监昕器的方法addLifecycleListener 、findLifecycleListeners 和removeLifecycleListener,分别用来添加、查找和删除LifecycleListener 类型的监听器。
  • 定义了4 个生命周期的方法: init 、start、stop 和destroy,用于执行生命周期的各个阶段的操作。
  • 定义了获取当前状态的两个方法getState 和getStateName ,用来获取当前的状态,getState 的返回值LifecycleState 是枚举类型,里边列举了生命周期的各个节点,getStateName 方法返回String 类型的状态的名字,主要用于JMX中。
public interface Lifecycle {

public static final String BEFORE_INIT_EVENT = "before_init";

public static final String AFTER_INIT_EVENT = "after_init";

public static final String START_EVENT = "start";

public static final String BEFORE_START_EVENT = "before_start";

public static final String AFTER_START_EVENT = "after_start";

public static final String STOP_EVENT = "stop";

public static final String BEFORE_STOP_EVENT = "before_stop";

public static final String AFTER_STOP_EVENT = "after_stop";

public static final String AFTER_DESTROY_EVENT = "after_destroy";

public static final String BEFORE_DESTROY_EVENT = "before_destroy";

public static final String PERIODIC_EVENT = "periodic";

public static final String CONFIGURE_START_EVENT = "configure_start";

public static final String CONFIGURE_STOP_EVENT = "configure_stop";

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;

public LifecycleState getState();

public String getStateName();

public interface SingleUse {
}
}

2.2 LifecycleBase

  Lifecycle 的默认实现是org.apache.catalina.util.LifecycleBase ,所有实现了生命周期的组件都直接或间接地继承向LifecycleBase, LifecycleBase 为Lifecycle 里的接口方法提供了默认实现:监听器管理是专门使用了一个LifecycleSupport 类来完成的, LifecycleSupport 中定义了一个LifecycleListener 数组类型的属性来保存所有的监听器,然后并定义了添加、删除、查找和执行监听器的方法;生命周期方法中设置了相应的状态并调用了相应的模板方法,init 、start 、stop 和destroy 所对应的模板方法分别是initlntemal 、startlntemal 、stoplnternal 和destroyInternal 方法,这四个方法由子类具体实现,所以对于子类来说,执行生命周期处理的方法就是initlntemal 、startlnternal 、stopintemal 和destroyInternal ;组件当前的状态在生命周期的四个方法中已经设置好了,所以这时直接返回去就可以了。下面分别来看一下实现的过程。
  三个管理监昕器的方法
  管理监听器的添加、查找和删除的方法是使用LifecycleSupport 来管理的,代码如下:

private LifecycleSupport lifecycle = new LifecycleSupport(this);
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}

@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}

@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}

LifecycleSupport 监听器是通过一个数组属性listeners 来保存的,代码如下:

public final class LifecycleSupport {
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;

}
private Lifecycle lifecycle = null;

private LifecycleListener listeners[] = new LifecycleListener[0];

private final Object listenersLock = new Object(); // Lock object for changes to listeners

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

}

public LifecycleListener[] findLifecycleListeners() {

return listeners;

}

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

}

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

}
}

  四个生命周期方法
  四个生命周期方法的实现中首先判断当前的状态和要处理的方法是否匹配,如果不匹配就会执行相应方法使其匹配(如在init 之前调用了start,这时会先执行init 方法),或者不处理甚至抛异常,如果匹配或者处理后匹配了,则会调用相应的模板方法并设置相应的状态。
  LifecycleBase 中的状态是通过LifecycleState 类型的state 属性来保存的,最开始初始化值为LifecycleState.NEW。我们来看一下init 方法:

@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}

  init 方法中如果状态不是LifecycleState.NEW 会调用invalidTransition 方法抛出异常,invalidTransition 方法专门用于处理不符合要求的状态,在另外三个方法中如果状态也不合适而且不能进行别的处理,也会调用invalidTransition 方法,其代码如下:

private void invalidTransition(String type) throws LifecycleException {
String msg = sm.getString("lifecycleBase.invalidTransition", type,
toString(), state);
throw new LifecycleException(msg);
}

start 方法:

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

try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
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);
}
} 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);
}
}

  start 方法在启动前先判断是不是已经启动了,如果已经启动了则直接返回,如果没有初始化会先执行初始化,如果是失败在状态就会调用stop 方法进行关闭,如果状态不是前面那些也不是刚初始化完或者已经停止了则会抛出异常。如果状态是刚初始化完或者已经停止了,则会先将状态设置为LifecycleState.STARTING_PREP ,然后执行startlntemal 模板方法调用子类的具体启动逻辑进行启动,最后根据是否启动成功设置相应的状态。其实主要就是各种状态的判断设置, stop 和destroy 方法的实现过程也差不多,就不具体分析了。设置状态的setStateintemal 方法中除了设置状态还可以检查设置的状态合不合逻辑,并且会在最后发布相应的事件,其代码如下:

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) {
if (state == null) {
invalidTransition("null");
return;
}
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))) {
invalidTransition(state.name());
}
}

this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}

  setStateintemal 方法中通过check 参数判断是否需要检查传人的状态,如果需要检查则会检查传入的状态是否为空和是否符合逻辑,最后将传入的状态设置到state 属性,并调用fireLifecycleEvent 方法处理事件, fireLifecycleEvent 方法调用了LifecycleSupport 的fireLifecycleEvent 方法来具体处理。
两个获取当前状态的方法
  在生命周期的相应方法中已经将状态设置到了state 属性,所以获取状态的两个方法的实现就非常简单了,直接将state 返回就可以了,代码如下:

    @Override
public LifecycleState getState() {
return state;
}
@Override
public String getStateName() {
return getState().toString();
}