概述
从Tomcat-整体架构中看到Tomcat涉及众多有生命周期概念的组件,包括Server/Service/Engine/Host/Context/Wrapper,那么如何统一管理这些组件(也即如何管理Tomcat生命周期)就是设计的要点,本节就来看下Tomcat的设计。
1. 组合模式
把生命周期的过程抽象成LifeCycle
接口,每个具体的组件去实现这些方法
public interface Lifecycle {
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
.......
}
在父组件的init()方法里需要创建子组件并调用子组件的init()方法。同样,在父组件的start()方法里也需要调用子组件的start()方法,因此调用者可以无差别的调用各组件的init()方法和start()方法,这就是组合模式
的使用,并且只要调用最顶层组件,也就是Server组件的init()和start()方法,整个Tomcat就被启动起来了。
2. 观察者模式
在LifeCycle接口里加入了管理监听器的方法,另外定义一个Enum来表示组件有哪些状态,以及处在什么状态会触发什么样的事件;比如NEW状态表示组件刚刚被实例化;而当init()方法被调用时,状态就变成INITIALIZING状态,这个时候,就会触发BEFORE_INIT_EVENT事件,如果有监听器在监听这个事件,它的方法就会被调用。
public interface Lifecycle {
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public LifecycleState getState();
public String getStateName();
......
}
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);
.....
}
// 状态流转过程
* 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() |
* ----»-----------------------------»------------------------------
*
组件的init()和start()调用是由它的父组件的状态变化触发的,上层组件的初始化会触发子组件的初始化,上层组件的启动会触发子组件的启动,因此把组件的生命周期定义成一个个状态,把状态的转变看作是一个事件。而事件是有监听器的,在监听器里可以实现一些逻辑,并且监听器也可以方便的添加和删除,这就是典型的观察者模式
。
3. 模板方法模式
Tomcat定义一个基类LifeCycleBase来实现LifeCycle接口,把一些公共的逻辑放到基类中去,比如生命状态的转变与维护、生命事件的触发以及监听器的添加和删除等,而子类就负责实现自己的初始化、启动和停止等方法。
// 以init方法为例分析
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) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}
1. invalidTransition
检查状态的合法性,比如当前状态必须是NEW然后才能进行初始化。
2. setStateInternal
触发INITIALIZING事件的监听器:在这个setStateInternal方法里,会调用监听器的业务方法。
3. initInternal
调用具体子类实现的抽象方法initInternal()方法。我在前面提到过,为了实现一键式启动,具体组件在实现initInternal()方法时,又会调用它的子组件的init()方法。
4. setStateInternal
子组件初始化后,触发INITIALIZED事件的监听器,相应监听器的业务方法就会被调用。
LifeCycleBase实现LifeCycle接口的方法并设置为final,在实现方法中实现公共逻辑,提供对应的xxxInternal()方法供子类实现,这是典型的模板方法模式
。
-------over--------