你可能不那么知道的Tomcat生命周期管理 | 博学谷狂野架构师
创始人
2025-06-01 11:31:01
0

Tomcat生命周期管理

img

各种组件如何统一管理

Tomcat的架构设计是清晰的、模块化、它拥有很多组件,加入在启动Tomcat时一个一个组件启动,很容易遗漏组件,同时还会对后面的动态组件拓展带来麻烦。如果采用我们传统的方式的话,组件在启动过程中如果发生异常,会很难管理,比如你的下一个组件调用了start方法,但是如果它的上级组件还没有start甚至还没有init的话,Tomcat的启动会非常难管理,因此,Tomcat的设计者提出一个解决方案:用Lifecycle管理启动,停止、关闭。

生命周期统一接口

Tomcat内部架构中各个核心组件有包含与被包含关系,例如:Server包含了Service.Service又包含了Container和Connector,这个结构有一点像数据结构中的树,树的根结点没有父节点,其他节点有且仅有一个父节点,每一个父节点有0至多个子节点。所以,我们可以通过父容器启动它的子容器,这样只要启动根容器,就可以把其他所有的容器都启动,从而达到了统一的启动,停止、关闭的效果。

所有所有组件有一个统一的接口——Lifecycle,把所有的启动、停止、关闭、生命周期相关的方法都组织到一起,就可以很方便管理Tomcat各个容器组件的生命周期。

Lifecycle其实就是定义了一些状态常量和几个方法,主要方法是init,start,stop三个方法。

例如:Tomcat的Server组件的init负责遍历调用其包含所有的Service组件的init方法。

注意:Server只是一个接口,实现类为StandardServer,有意思的是,StandardServer没有init方法,init方法是在哪里,其实是在它的父类LifecycleBase中,这个类就是统一的生命周期管理。

COPYpublic class StandardService extends LifecycleMBeanBase implements Servicepublic abstract class LifecycleMBeanBase extends LifecycleBaseimplements JmxEnabled

LifecycleBase

COPYpublic abstract class LifecycleBase implements Lifecycle {@Overridepublic final synchronized void init() throws LifecycleException {//这个就是为了防止 组件启动的顺序不对if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);}try {//只打印核心组件if(this.getClass().getName().startsWith("org.apache.catalina.core")||this.getClass().getName().startsWith("org.apache.catalina.connector")){System.out.println(this.getClass()+"--init()");}setStateInternal(LifecycleState.INITIALIZING, null, false);//调用子类的initInternal方法initInternal();setStateInternal(LifecycleState.INITIALIZED, null, false);} catch (Throwable t) {handleSubClassException(t, "lifecycleBase.initFail", toString());}}}

所以StandardServer最终只会调用到initInternal方法,这个方法会初始化子容器Service的init方法

为什么LifecycleBase这么玩,其实很多架构源码都是这么玩的,包括JDK的容器源码都是这么玩的,一个类,有一个接口,同时抽象一个抽象骨架类,把通用的实现放在抽象骨架类中,这样设计就方便组件的管理,使用LifecycleBase骨架抽象类,在抽象方法中就可以进行统一的处理。

LifeCycle源码分析

作用

组件生命周期方法的通用接口。 Catalina组件可以实现此接口(以及它们支持的功能的适当接口),以便提供一致的机制来启动和停止组件

状态图

Tomcat中的事件触发是通过这些状态来判定的。

COPY*            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()                             |* ----»-----------------------------»------------------------------

接口定义

Lifecycle接口统一管理Tomcat生命周期。一共做了4件事:

  • 定义13个string类型常量,用于LifecycleEvent时间的type属性中,用于区分组件发出的LifecycleEvent事件时的状态。
  • 定义三个管理监听器的方法,addLifecycleListener、findLifecycleListeners、removeLifecycleListener。
  • 定义4个生命周期的方法,init、start、stop、destory,用于执行生命周期的各个阶段的操作。
  • 定义了获取当前状态的两个方法,getState、getStateName、用于获取当前的状态。
COPYpublic interface Lifecycle {// 13个状态常量值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";// 3个监听器方法public void addLifecycleListener(LifecycleListener listener);public LifecycleListener[] findLifecycleListeners();public void removeLifecycleListener(LifecycleListener listener);// 4个生命周期方法public void init() throws LifecycleException;public void start() throws LifecycleException;public void stop() throws LifecycleException;public void destroy() throws LifecycleException;// 2个当前状态方法public LifecycleState getState();public String getStateName();
}

默认实现类

COPYpublic abstract class LifecycleBase implements Lifecycle {// 源组件的当前状态,不同状态触发不同事件private volatile LifecycleState state = LifecycleState.NEW;
}

监听器相关方法

事件监听器需要三个参与者:

  • 事件对象:用于封装事件的信息,在事件监听器接口的同一方法中作为参数使用,继承自java.util.EventObject类。
  • 事件源:触发事件的源头,不同事件源触发不同事件类型。
  • 事件监听器:负责监听事件源发出的事件。实现 java.util.EventListener 接口。
COPY// 用于事件通知的已注册LifecycleListener列表
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);
}// 子类根据当前状态触发不同事件,实现不同操作
protected void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(this, type, data);for (LifecycleListener listener : lifecycleListeners) {listener.lifecycleEvent(event);}
}

生命周期方法

LifecycleBase 类是Lifecycle 接口的默认实现,所有实现了生命周期的组件都直接或者间接的继承自LifecycleBase。

init方法
COPY@Override
public final synchronized void init() throws LifecycleException {// 只有 NEW 状态可以调用if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);}// 设置 生命周期状态 -- INITIALIZING,触发相应事件setStateInternal(LifecycleState.INITIALIZING, null, false);// 模板方法,由具体子类实现initInternal();// 执行完成,设置生命周期状态 -- INITIALIZED,触发相应事件setStateInternal(LifecycleState.INITIALIZED, null, false);
}
Start方法
COPY@Override
public final synchronized void start() throws LifecycleException {// 此三种状态不执行if (LifecycleState.STARTING_PREP.equals(state) ||      LifecycleState.STARTING.equals(state) ||LifecycleState.STARTED.equals(state)) {return;}// NEW 状态 执行 init 方法if (state.equals(LifecycleState.NEW)) {init();// 启动失败,调用 stop 方法} else if (state.equals(LifecycleState.FAILED)) {stop();// 其它状态,非法操作} else if (!state.equals(LifecycleState.INITIALIZED) &&!state.equals(LifecycleState.STOPPED)) {throw new LifecycleException()}// 设置启动状态为 STARTING_PREP【开始准备】setStateInternal(LifecycleState.STARTING_PREP, null, false);startInternal();// 调用完成后判断组件启动状态if (state.equals(LifecycleState.FAILED)) {stop();} else if (!state.equals(LifecycleState.STARTING)) {throw new LifecycleException();} else {setStateInternal(LifecycleState.STARTED, null, false);}
}
stop方法
COPY@Override
public final synchronized void stop() throws LifecycleException {// STOPPING_PREP、STOPPING、STOPPED此三种状态不予执行if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||LifecycleState.STOPPED.equals(state)) {return;}// 如果状态为 NEW、修改为 STOPPEDif (state.equals(LifecycleState.NEW)) {state = LifecycleState.STOPPED;return;}// 不为 STARTED、FAILED 2种状态,抛出异常if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {throw new LifecycleException();}try {// 启动失败,触发事件,否则设置生命周期状态if (state.equals(LifecycleState.FAILED)) {fireLifecycleEvent(BEFORE_STOP_EVENT, null);} else {setStateInternal(LifecycleState.STOPPING_PREP, null, false);}// 调用模板方法stopInternal();if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {throw new LifecycleException();}setStateInternal(LifecycleState.STOPPED, null, false);} catch (Throwable t) {setStateInternal(LifecycleState.FAILED, null, false);throw new LifecycleException();} finally {if (this instanceof Lifecycle.SingleUse) {setStateInternal(LifecycleState.STOPPED, null, false);destroy();}}
}
destroy方法
COPY@Override
public final synchronized void destroy() throws LifecycleException {// 启动失败,先调用 stop 方法if (LifecycleState.FAILED.equals(state)) {stop();}// DESTROYING、DESTROYED不执行了if (LifecycleState.DESTROYING.equals(state) ||LifecycleState.DESTROYED.equals(state)) {return;}// 非法状态if (!state.equals(LifecycleState.STOPPED) &&!state.equals(LifecycleState.FAILED) &&!state.equals(LifecycleState.NEW) &&!state.equals(LifecycleState.INITIALIZED)) {throw new LifecycleException();}try {setStateInternal(LifecycleState.DESTROYING, null, false);destroyInternal();setStateInternal(LifecycleState.DESTROYED, null, false);} catch (Throwable t) {setStateInternal(LifecycleState.FAILED, null, false);throw new LifecycleException();}
}
设置状态方法
COPYprivate synchronized void setStateInternal(LifecycleState state,Object data, boolean check) throws LifecycleException {// 检查参数if (check) {if (state == null) {throw new LifecycleException();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))) {throw new LifecycleException();}}this.state = state;String lifecycleEvent = state.getLifecycleEvent();if (lifecycleEvent != null) {fireLifecycleEvent(lifecycleEvent, data);}
}

监听机制

事件监听器需要三个参与者:

  • 事件对象—用于封装事件的信息,在事件监听器接口的统一方法中作为参数,一般继承 java.util.EventObjecct类。
  • 事件源—触发事件对的源头,不同事件源触发不同事件。
  • 事件监听器—负责监听事件源发出的事件,发生事件时,事件源调用事件监听器的统一方法处理。监听器一般实现java.util.EventListener接口。
COPYpublic final class LifecycleEvent extends java.util.EventObject {public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {super(lifecycle);this.type = type;this.data = data;}
}
COPYpublic interface LifecycleListener {public void lifecycleEvent(LifecycleEvent event);
}
COPYpublic class HostConfig implements LifecycleListener {@Overridepublic void lifecycleEvent(LifecycleEvent event) {try {host = (Host) event.getLifecycle();if (host instanceof StandardHost) {setCopyXML(((StandardHost) host).isCopyXML());setDeployXML(((StandardHost) host).isDeployXML());setUnpackWARs(((StandardHost) host).isUnpackWARs());setContextClass(((StandardHost) host).getContextClass());}} catch (ClassCastException e) {return;}// Process the event that has occurredif (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {check();} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {beforeStart();} else if (event.getType().equals(Lifecycle.START_EVENT)) {start();} else if (event.getType().equals(Lifecycle.STOP_EVENT)) {stop();}}
}
COPY// LifecycleBase.startInternal
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {fireLifecycleEvent(lifecycleEvent, data);
}protected void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(this, type, data);for (LifecycleListener listener : lifecycleListeners) {listener.lifecycleEvent(event);}
}

模板方法

四个模板方法,由子类具体实现

COPYprotected abstract void initInternal() throws LifecycleException;
protected abstract void startInternal() throws LifecycleException;
protected abstract void stopInternal() throws LifecycleException;
protected abstract void destroyInternal() throws LifecycleException;

总结

通过提供init、start、stop、destory方法,通过相应的模板方法【模板设计模式】,提供组件的统一生命周期的管理、事件调度。

本文由传智教育博学谷狂野架构师教研团队发布。

如果本文对您有帮助,欢迎关注点赞;如果您有任何建议也可留言评论私信,您的支持是我坚持创作的动力。

转载请注明出处!

相关内容

热门资讯

芯朋微将于6月18日召开股东大... 金融界6月2日消息,芯朋微发布公告,将于2025年6月18日召开第1次临时股东大会,网络投票同日进行...
“开盒”游戏害了多少孩子?看这... 5月29日,在最高人民法院“六一”儿童节公众开放日活动上,由最高人民法院新闻局、民一庭、人民法院出版...
原创 一... 近期,伴随着中国积极推行国际调解机制的浪潮,历史冤家柬埔寨与泰国却在边境地区上演了一场短暂却引发广泛...
2025深圳最新购房政策汇总! 深圳最新的购房政策是如何的? 今日小编为大家整理 2025年深圳买房政策汇总 大家一起来看看 一、...
南昌南斯友好路两家“海湾石油”... 今天(2日)上午 多名消费者向《都市现场》反映 他们在南昌南斯友好路上的两家“海湾石油” 预付充值了...
曝拜仁与莱奥密谈!AC米兰索要... 足坛转会市场再起波澜!德甲巨无霸拜仁慕尼黑,这次将目光投向了亚平宁半岛,盯上了AC米兰的王牌边锋——...
曼联2500万甩卖“铁腰”,那... 提起苏格兰中场斯科特·麦克托米奈,如今的足坛可谓是无人不知,无人不晓。但就在2024年夏天,当曼联以...
行驶中推送广告、恶意更新隐私政... 深蓝汽车法务部今日(6 月 2 日)发布声明提出,部分网络内容发布 “深蓝汽车在行驶过程中推送广告严...
德国银行高管:美政府政策频繁变... 根据德国《商报》6月2日刊发的专访文章,德国国家开发银行复兴信贷银行董事会主席斯特凡·温特尔斯指出,...
过程不到2分钟!深夜母子潜入建... 前几天, 曲靖会泽一加气站内的井盖被盗, 幸好工作人员发现及时 才没造成人员受伤, 民警随即展开调查...