Tomcat源码分析 | 一文详解生命周期机制Lifecycle
目录
- 什么是Lifecycle?
- Lifecycle方法
- LifecycleBase
- 增加、删除和获取监听器
- init()
- start()
- stop()
- destroy()
- 模板方法
- 总结
前言
Tomcat里面有各种各样的组件,每个组件各司其职,组件之间又相互协作共同完成web服务器这样的工程。在这些组件之上,Lifecycle(生命周期机制)至关重要!在学习各个组件之前,我们需要看看Lifecycle是什么以及能做什么?实现原理又是怎样的?
什么是Lifecycle?
Lifecycle,其实就是一个状态机,对组件的由生到死状态的管理。
当组件在STARTING_PREP、STARTING或STARTED时,调用start()方法没有任何效果
当组件在NEW状态时,调用start()方法会导致init()方法被立刻执行,随后start()方法被执行
当组件在STOPPING_PREP、STOPPING或STOPPED时,调用stop()方法没有任何效果
当一个组件在NEW状态时,调用stop()方法会将组件状态变更为STOPPED,比较典型的场景就是组件启动失败,其子组件还没有启动。当一个组件停止的时候,它将尝试停止它下面的所有子组件,即使子组件还没有启动。
Lifecycle方法
我们看看Lifecycle有哪些方法,如下所示:
public interface Lifecycle {
// 添加监听器
public void addLifecycleListener(LifecycleListener listener);
// 获取所以监听器
public LifecycleListener[] findLifecycleListeners();
// 移除某个监听器
public void removeLifecycleListener(LifecycleListener listener);
// 初始化方法
public void init() throws LifecycleException;
// 启动方法
public void start() throws LifecycleException;
// 停止方法,和start对应
public void stop() throws LifecycleException;
// 销毁方法,和init对应
public void destroy() throws LifecycleException;
// 获取生命周期状态
public LifecycleState getState();
// 获取字符串类型的生命周期状态
public String getStateName();
}
LifecycleBase
LifecycleBase是Lifecycle的基本实现。我们逐一来看Lifecycle的各个方法。
增加、删除和获取监听器
private final List<LifecycleListener> 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);
}
- 生命周期监听器保存在一个线程安全的List中,CopyOnWriteArrayList。所以add和remove都是直接调用此List的相应方法。
- findLifecycleListeners返回的是一个数组,为了线程安全,所以这儿会生成一个新数组。
init()方法
@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 (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", this, state));
}
// 是否校验状态
if (check) {
// Must have been triggered by one of the abstract methods (assume
// code in this class is correct)
// null is never a valid state
// state不允许为null
if (state == null) {
invalidTransition("null");
// Unreachable code - here to stop eclipse complaining about
// a possible NPE further down the method
return;
}
// Any method can transition to failed
// startInternal() permits STARTING_PREP to STARTING
// stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
// STOPPING
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))) {
// No other transition permitted
invalidTransition(state.name());
}
}
// 设置状态
this.state = state;
// 触发事件
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
我们看看fireLifecycleEvent方法,
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);
}
首先, 创建一个事件对象, 然通知所有的监听器发生了该事件.并做响应.
start()方法
@Override
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)) {
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;
}
// `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)) {
// 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 {
// 设置状态为STARTED
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);
}
}
stop()方法
@Override
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)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
}
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)) {
// Don't transition to STOPPING_PREP as that would briefly mark the
// component as available but do ensure the BEFORE_STOP_EVENT is
// fired
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
// 设置状态为STOPPING_PREP
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
// stop逻辑,抽象方法,组件自行实现
stopInternal();
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
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) {
// Complete stop process first
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}
destroy()方法
@Override
public final synchronized void destroy() throws LifecycleException {
// `FAILED`状态时,直接触发stop()逻辑
if (LifecycleState.FAILED.equals(state)) {
try {
// Triggers clean-up
stop();
} catch (LifecycleException e) {
// Just log. Still want to destroy.
log.warn(sm.getString(
"lifecycleBase.destroyStopFail", toString()), e);
}
}
// `DESTROYING`和`DESTROYED`时,忽略destroy的执行
if (LifecycleState.DESTROYING.equals(state) ||
LifecycleState.DESTROYED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
} else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
// Rather than have every component that might need to call
// destroy() check for SingleUse, don't log an info message if
// multiple calls are made to destroy()
log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
}
return;
}
// 非法状态判断
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
}
try {
// destroy前状态设置
setStateInternal(LifecycleState.DESTROYING, null, false);
// 抽象方法,组件自行实现
destroyInternal();
// destroy后状态设置
setStateInternal(LifecycleState.DESTROYED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.destroyFail",toString()), t);
}
}
模板方法
从上述源码看得出来,LifecycleBase是使用了状态机+模板模式来实现的。模板方法有下面这几个:
// 初始化方法
protected abstract void initInternal() throws LifecycleException;
// 启动方法
protected abstract void startInternal() throws LifecycleException;
// 停止方法
protected abstract void stopInternal() throws LifecycleException;
// 销毁方法
protected abstract void destroyInternal() throws LifecycleException;
总结
Lifecycle其实非常简单,代码也不复杂,但是剖析其实现对于我们理解组件的生命周期有很大的帮助,也有助于我们对设计模式的回顾。
Tomcat源码分析 | 一文详解生命周期机制Lifecycle的更多相关文章
- 【集合框架】JDK1.8源码分析之ArrayList详解(一)
[集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...
- nginx源码分析线程池详解
nginx源码分析线程池详解 一.前言 nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...
- vuex 源码分析(六) 辅助函数 详解
对于state.getter.mutation.action来说,如果每次使用的时候都用this.$store.state.this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我 ...
- vuex 源码分析(五) action 详解
action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...
- Linux进程调度与源码分析(二)——进程生命周期与task_struct进程结构体
1.进程生命周期 Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行.而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件 ...
- Golang源码分析之目录详解
开源项目「go home」聚焦Go语言技术栈与面试题,以协助Gopher登上更大的舞台,欢迎go home~ 导读 学习Go语言源码的第一步就是了解先了解它的目录结构,你对它的源码目录了解多少呢? 目 ...
- Tomcat源码分析 (十)----- 彻底理解 Session机制
Tomcat Session 概述 首先 HTTP 是一个无状态的协议, 这意味着每次发起的HTTP请求, 都是一个全新的请求(与上个请求没有任何联系, 服务端不会保留上个请求的任何信息), 而 Se ...
- Java 容器源码分析之集合类详解
集合类说明及区别 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └W ...
- Cloudera Impala源码分析: SimpleScheduler调度策略详解包括作用、接口及实现等
问题导读:1.Scheduler任务中Distributed Plan.Scan Range是什么?2.Scheduler基本接口有哪些?3.QuerySchedule这个类如何理解?4.Simple ...
随机推荐
- Pod 健康检查和服务可用性检查
Kubernetes 对 Pod 的健康状态可以通过两类探针来检查:LivenessProbe 和 ReadinessProbe,kubelet 定期执行这两类探针来针对容器的健康状况. Livene ...
- 腾讯发布 K8s 多集群管理开源项目 Clusternet
11月4日,在腾讯数字生态大会上,腾讯宣布了云原生领域一项重磅开源进展-- K8s 多集群管理项目 Clusternet 正式开源. Clusternet 由腾讯联合多点生活.QQ音乐.富途证券.微众 ...
- dotnet 6 使用 CreateSymbolicLink 创建文件夹符号链接
本文告诉大家如何使用 dotnet 6 提供的 Directory.CreateSymbolicLink 和 File.CreateSymbolicLink 方法创建文件夹和文件的符号链接 Direc ...
- WPF进阶技巧和实战09-事件(2-多点触控)
多点触控输入 多点触控输入和传统的基于比的输入的区别是多点触控识别手势,用户可以移动多根手指以执行常见的操作,放大,旋转,拖动等. 多点触控的输入层次 WPF允许使用键盘和鼠标的高层次输入(例如单击和 ...
- Nginx面试题(总结最全面的面试题!!!)
https://blog.csdn.net/weixin_43122090/article/details/105461971
- 为什么不直接去Arraylist list = new Arraylist();而是直接通过List list = new ArrayList();使用接口的好处
ArrayList不是继承List接口,是实现了List接口. 你写成ArrayList arrayList = new ArrayList();这样不会有任何问题.和List list = new ...
- 菜鸡的Java笔记 第十一 - java 封装性
1.1封装的基础实现. 封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口.面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治.封装的对象,这些对象通过一个受保 ...
- [luogu4548]歌唱王国
(可以参考hdu4652,因此推导过程比较省略) 类似的定义$f_{i}$和$g_{i}$,同样去插入$len$个字符,但注意到并不是任意一个位置都可以作为结尾,$i+j$可以作为结尾当且仅当$s[0 ...
- [atARC098F]Donation
贪心,一定在最后一次经过某节点时付出$b_{u}$,条件是付出后$W\ge \max(a_{i}-b_{i},0)$(同时也可以仅考虑这个限制,因为$W$在过程中不会增大) 假设"最后一次经 ...
- 一文详解 OpenGL ES 3.x 渲染管线
OpenGL ES 构建的三维空间,其中的三维实体由许多的三角形拼接构成.如下图左侧所示的三维实体圆锥,其由许多三角形按照一定规律拼接构成.而组成圆锥的每一个三角形,其任意一个顶点由三维空间中 x.y ...