Tomcat知多少 -- 组件生命周期Lifecycle

Tomcat中存在着诸多的组件,如Server、Service、Engine、Host、Context等,这些组件都遵从Tomcat的生命周期管理,比如当Catalina调用start()方法启动Tomcat时,这些组件会随之启动,当调用stop()关闭时,这些组件会随之关闭。

理解Tomcat的生命周期管理对于分析Tomcat源码很有帮助,方便快速理清源码结构,深入源码时也会有迹可循。

生命周期的顶层设计

Tomcat生命周期管理的顶层设计如下图所示:

接口Lifecycle定义了生命周期中的四种动作以及生命周期中的各种事件名称(这里没有列出);

枚举类LifecycleState定义了生命周期中的各种状态;

LifecycleBaseLifecycle接口的抽象实现类,像StandardServerStandardSevice等Tomcat的核心组件都是它的子类,该类主要内容是规定了四种动作发生时组件状态之间的转换,以及自动调用先前注册的事件监听动作。它拥有一个LifecycleState类型的成员变量,用于记录组件的当前状态,还使用一个容器变量来存储注册在该组件上的事件监听器;

LifecycleEvent用于表示声明周期中发生的一个事件,它的成员有表示事件来源的组件source,发生的事件类型type,以及事件发生时携带的数据;

LifecycleListener是事件监听器的接口,它只有一个方法声明lifecycleEvent(event:LifecycleEvent),该方法接收一个LifecycleEvent实例对象,其具体实现类将根据事件类型来执行相应的动作(可以查看VersionLoggerListener的源码作为一个实现的参考)。

状态转移图

LifecycleBase规定的四种动作发生时组件状态之间的转换图如下所示。

可以看到,生命周期中的状态转移还是比较复杂的,各组件由NEW状态开始,到DESTROYED状态结束,中间通过不同的方法调用实现合法的状态转移,而不合法的状态转移都会导致状态置为FAILED,接着调用destroy()方法来销毁。

这一块在实现上实际上是模板方法模式一个应用,通过实现Lifecycle接口中的四个方法来定义状态转移,同时又声明四个抽象方法xxxInternal(),将具体的功能留给子类来实现。

当然在状态转以上,Tomcat并没有使用到状态模式,而是使用了许多if ... else...判断语句来定义合法的状态转移,这样的好处在于避免了为每个状态定义一个类,减少了类的数目。

事件监听

LifecycleBase使用观察者模式来实现了事件的响应处理。

首先,它定义了一个List容器用于保存注册的监听器:

/**
 * The list of registered LifecycleListeners for event notifications.
 */
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

这里使用了CopyOnWriteArrayList,通过读写分离来提高并发环境下的事件响应效率。

最后,通过protected void fireLifecycleEvent(String type, Object data)方法响应相应事件。

如下图所示,以init()的调用为例:

首先使用setStateInternal()方法改变状态为INITLALIZING,该方法内部会调用fireLifecycleEvent()方法,接着会根据事件类型先创建一个LifecycleEvent实例event,然后将event作为参数调用LifecycleListenerlifecycleEvent()方法,该方法就是各个具体的监听器响应事件的地方。随后具体的初始化动作在initInternal()中完成后,在设置状态为INITIALIZED,同时也会触发相关的监听事件。

posted @ 2020-05-09 10:03  SanjiApollo  阅读(342)  评论(0编辑  收藏  举报