参考资料:
《Tomcat - 组件生命周期管理:LifeCycle》
《Tomcat - 事件的监听机制:观察者模式》
前文:
《Tomcat源码:启动类Bootstrap与Catalina的加载》
写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。
在前文中我们介绍了tomcat的启动类加载,最后介绍到了getServer().init(),这里的getServer()就是获取加载server.xml时创建的StandardServer对象,StandardServer对象即server接口的实现。
在整个过程中涉及到的组件server、service、engine、context等容器的实现类StandardServer、StandardService、StandardEngine、StandardContext都继承了各自的接口与LifecycleBase抽象类。LifecycleBase抽象类实现了对这些容器生命周期的统一管理,本文我们就来介绍下它。(下图中右侧即为生命周期管理,左半侧为JMX,关于JMX的内容我以前有专门介绍过,本文就不重复了《Java8之JMX与MBean》)
目录
前言
一、LifeCycle接口
1、接口内容
2、生命周期状态
3、监听器
3.1、观察者模式
3.2、监听器
二、LifecycleBase - LifeCycle的基本实现
1、监听器
2、生命周期相关
2.1、init
2.2、start
2.3、stop
LifeCycle接口可以分为三个模块,监听器处理、生命周期方法与状态。简单来说各个组件都有个生命周期状态(类似线程的就绪、执行、阻塞等),在执行生命周期方法后产生变化,可以通过getState方法来获取,同时一个组件在状态变化时可以通过被注册在其上的监听器触发一些处理操作。
public interface Lifecycle {
/** 第1类:监听器处理 **/
// 添加监听器
public void addLifecycleListener(LifecycleListener listener);
// 获取所以监听器
public LifecycleListener[] findLifecycleListeners();
// 移除某个监听器
public void removeLifecycleListener(LifecycleListener listener);
/** 第2类:生命周期方法 **/
// 初始化方法
public void init() throws LifecycleException;
// 启动方法
public void start() throws LifecycleException;
// 停止方法,和start对应
public void stop() throws LifecycleException;
// 销毁方法,和init对应
public void destroy() throws LifecycleException;
/** 第3类:生命周期状态 **/
// 获取生命周期状态
public LifecycleState getState();
// 获取字符串类型的生命周期状态
public String getStateName();
}
在枚举类LifecycleState里Tomcat给各个组件定义了一些生命周期中的状态,这些状态主要用于帮助我们对组件进行管控,至于具体的管控操作我们会在将每个组件的时候介绍,现在只需要知道这些组件都类似线程一样有自己的生命周期状态且可以进行转换即可。
需要注意的是,每个状态都有一个lifecycleEvent参数,这在下文将监听器的时候会用到。
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;
LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}
public boolean isAvailable() {
return available;
}
public String getLifecycleEvent() {
return lifecycleEvent;
}
}
state中各状态间的转换关系如下图,可以看到最后一句提示所有的状态都可以转换为FAILED。
要介绍监听器我们就要先了解下观察者模式(又叫发布订阅模式)。如果存在对象间的一对多关系,当这个对象发生变化时我们想让依赖他的其他对象都得到通知并被自动更新就可以使用观察者模式。
实现方法为在被观察类上维护一个存储观察者的List(依赖这个对象的类的集合),当被依赖对象发生变化时遍历这个集合,将变化告知到每个观察者,下面来看下具体实现。
首先是观察者,对于一个接口Observer我们提供了三种不同的实现,每种实现都重写了update方法。
// 观察者接口
public abstract class Observer {
public abstract void update(String msg);
}
// 第一个观察者
public class F_Observer extends Observer {
public void update(String msg) {
System.out.println(F_Observer.class.getName() + " : " + msg);
}
}
// 第二个观察者
public class S_Observer extends Observer {
public void update(String msg) {
System.out.println(S_Observer.class.getName() + " : " + msg);
}
}
// 第三个观察者
public class T_Observer extends Observer {
public void update(String msg) {
System.out.println(T_Observer.class.getName() + " : " + msg);
}
}
然后是被观察者,维护一个存储观察者对象的List与add添加方法,当状态出现变化时通知所有的观察者。
public class Subject {
// 观察者集合
private List observers = new ArrayList<>();
// 状态变化后调用通知方法
public void setMsg(String msg) {
notifyAll(msg);
}
// 观察者订阅这个对象
public void addAttach(Observer observer) {
observers.add(observer);
}
// 通知所有订阅的观察者
private void notifyAll(String msg) {
for (Observer observer : observers) {
observer.update(msg);
}
}
}
测试类中我们将不同的观察者依次加入到被观察者中,然后改变被观察者的状态,此时所有的观察者就都能收到这个变化的通知了,运行结果为: test.F_Observer : msg changetest.S_Observer : msg changetest.T_Observer : msg change。
public class Main {
public static void main(String[] args) {
F_Observer fObserver = new F_Observer();
S_Observer sObserver = new S_Observer();
T_Observer tObserver = new T_Observer();
Subject subject = new Subject();
subject.addAttach(fObserver);
subject.addAttach(sObserver);
subject.addAttach(tObserver);
subject.setMsg("msg change");
}
}
tomcat容器中的监听器为LifecycleListener接口,当组件的状态发生变化时就会触发其中的lifecycleEvent来通知到依赖当前组件的对象,具体内容我们会在下文介绍。
public interface LifecycleListener {
void lifecycleEvent(LifecycleEvent event);
}
LifecycleBase是Lifecycle的基本实现。
生命周期监听器保存在一个线程安全的CopyOnWriteArrayList中。所以add和remove都是直接调用此List的相应方法。 findLifecycleListeners返回的是一个数组,为了线程安全,所以这儿会生成一个新数组。
private final List lifecycleListeners = new CopyOnWriteArrayList<>();
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}
@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
可以看到基本流程就是状态切换,切换过程中的具体操作留给了子类(即我们的各个组件如server、service等)去实现,熟悉spring的朋友肯定能一下子认出来这就是我们常用的模板模式。
@Override
public final synchronized void init() throws LifecycleException {
// 非NEW状态,不允许调用init()方法
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
// 初始化逻辑之前,先将状态变更为`INITIALIZING`
setStateInternal(LifecycleState.INITIALIZING, null, false);
// 初始化,该方法为一个abstract方法,需要组件自行实现
initInternal();
// 初始化完成之后,状态变更为`INITIALIZED`
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
// 初始化的过程中,可能会有异常抛出,这时需要捕获异常,并将状态变更为`FAILED`
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}
setStateInternal方法用于维护状态,同时在状态转换成功之后触发事件。为了状态的可见性,所以state声明为volatile类型的。
private volatile LifecycleState state = LifecycleState.NEW;。
private synchronized void setStateInternal(LifecycleState state,
Object data, boolean check) throws LifecycleException {
// 是否校验状态
if (check) {
// state不允许为null
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);
}
}
设置完 state 的状态之后,就触发该状态的事件了,通知事件监听器。这里的 LifecycleListener对象是在 Catalina 对象解析server.xml文件时就已经创建好并加到 lifecycleListeners 里的。
private final List lifecycleListeners = new CopyOnWriteArrayList<>();
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
可以看到start和init类似,先做校验后切换状态,期间的具体操作留给子类实现。
public final synchronized void start() throws LifecycleException {
// `STARTING_PREP`、`STARTING`和`STARTED时,将忽略start()逻辑
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
return;
}
// `NEW`状态时,执行init()方法
if (state.equals(LifecycleState.NEW)) {
init();
}
// `FAILED`状态时,执行stop()方法
else if (state.equals(LifecycleState.FAILED)) {
stop();
}
// 不是`INITIALIZED`和`STOPPED`时,则说明是非法的操作
else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
try {
// start前的状态设置
setStateInternal(LifecycleState.STARTING_PREP, null, false);
// start逻辑,抽象方法,由组件自行实现
startInternal();
// start过程中,可能因为某些原因失败,这时需要stop操作
if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
// 设置状态为STARTED
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
stop也和前两个方法类似,这里不多赘述。
public final synchronized void stop() throws LifecycleException {
// `STOPPING_PREP`、`STOPPING`和STOPPED时,将忽略stop()的执行
if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
LifecycleState.STOPPED.equals(state)) {
return;
}
// `NEW`状态时,直接将状态变更为`STOPPED`
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
// stop()的执行,必须要是`STARTED`和`FAILED`
if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
}
try {
// `FAILED`时,直接触发BEFORE_STOP_EVENT事件
if (state.equals(LifecycleState.FAILED)) {
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
// 设置状态为STOPPING_PREP
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
// stop逻辑,抽象方法,组件自行实现
stopInternal();
if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.AFTER_STOP_EVENT);
}
// 设置状态为STOPPED
setStateInternal(LifecycleState.STOPPED, null, false);
} 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) {
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}
至此,容器组件的生命周期管理基本内容差不多介绍完毕了,后续介绍的组件如server、service、engine、context等都会用到生命周期管理的方法,更详细的内容我们会在介绍容器组件的时候进行解析。