Tomcat9.0的生命周期

ops/2024/11/18 10:58:18/

生命周期接口

Tomcat拥有很多组件,假如在启动Tomcat时一个一个组件启动,这不仅麻烦而且容易遗漏组件,还会对后面的动态组件扩展带来麻烦。对于这个问题,Tomcat用Lifecycle管理启动、停止、关闭。

Tomcat内部架构中,Server包含Service, Service包含Container和Connector,往下再一层层包含。Tomcat就是以容器的方式来组织整个系统架构的,可以通过父容器启动它的子容器,这样只要启动根容器,即可把其他所有容器都启动,达到统一启动、停止、关闭的效果。

作为统一的接口,Lifecycle把所有的启动、停止、关闭、生命周期相关的方法都组织到一起,就可以很方便地管理Tomcat各个容器组件的生命周期。下面是Lifecycle接口详细的定义。

java">public interface Lifecycle {String BEFORE_INIT_EVENT = "before_init";String AFTER_INIT_EVENT = "after_init";String START_EVENT = "start";String BEFORE_START_EVENT = "before_start";String AFTER_START_EVENT = "after_start";String STOP_EVENT = "stop";String BEFORE_STOP_EVENT = "before_stop";String AFTER_STOP_EVENT = "after_stop";String AFTER_DESTROY_EVENT = "after_destroy";String BEFORE_DESTROY_EVENT = "before_destroy";String PERIODIC_EVENT = "periodic";String CONFIGURE_START_EVENT = "configure_start";String CONFIGURE_STOP_EVENT = "configure_stop";void addLifecycleListener(LifecycleListener listener);LifecycleListener[] findLifecycleListeners();void removeLifecycleListener(LifecycleListener listener);void init() throws LifecycleException;void start() throws LifecycleException;void stop() throws LifecycleException;void destroy() throws LifecycleException;LifecycleState getState();String getStateName();/*** Marker interface used to indicate that the instance should only be used* once. Calling {@link #stop()} on an instance that supports this interface* will automatically call {@link #destroy()} after {@link #stop()}* completes.*/interface SingleUse {}
}

从上面可以看出,Lifecycle其实就定义了一些状态常量和几个方法,例如:init、start、stop等方法,所有需要被生命周期管理的容器都要实现这个接口,并且各自被父容器的相应方法调用。例如,在初始化阶段,根容器Server组件会调用init方法,而在init方法里会调用它的子容器Service组件的init方法,以此类推。 

生命周期的转化

Lifecycle有个返回状态的方法getState(),返回的是LifecycleState枚举类型,此枚举包含了生命周期所有的状态,供组件状态之间转换使用。

java">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;}/*** May the public methods other than property getters/setters and lifecycle* methods be called for a component in this state? It returns* <code>true</code> for any component in any of the following states:* <ul>* <li>{@link #STARTING}</li>* <li>{@link #STARTED}</li>* <li>{@link #STOPPING_PREP}</li>* </ul>** @return <code>true</code> if the component is available for use,*         otherwise <code>false</code>*/public boolean isAvailable() {return available;}public String getLifecycleEvent() {return lifecycleEvent;}
}

整个生命周期内状态的转化相对较复杂,转换情况如图:

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

生命周期事件监听机制

在这么多状态之间转换,我们会有这样的需求:在某个状态发生前后做一些工作。Tomcat使用事件监听器模式来实现这样的功能:

  • 事件对象,封装事件的信息,在事件监听器接口的统一方法中作为参数使用,继承java. util.EventObject类
  • 事件源,触发事件的源头,不同的事件源会触发不同的事件类型
  • 事件监听器,负责监听事件源发出的事件

LifecycleEvent类就是事件对象,继承了EventObject类;LifecycleListener为事件监听器接口,里面只定义了一个方法lifecycleEvent (LifecycleEvent event)。很明显,LifecycleEvent作为这个方法的参数。最后缺一个事件源,一般来说,组件和容器就是事件源。父类LifecycleBase,帮助管理该组件或容器上的监听器,里面维护了一个监听器集合,并提供了注册、移除、触发监听器等方法,这样整个监听器框架就完成了。 

 事件对象:

java">public final class LifecycleEvent extends EventObject {private static final long serialVersionUID = 1L;/*** Construct a new LifecycleEvent with the specified parameters.** @param lifecycle Component on which this event occurred* @param type Event type (required)* @param data Event data (if any)*/public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {super(lifecycle);this.type = type;this.data = data;}/*** The event data associated with this event.*/private final Object data;/*** The event type this instance represents.*/private final String type;/*** @return the event data of this event.*/public Object getData() {return data;}/*** @return the Lifecycle on which this event occurred.*/public Lifecycle getLifecycle() {return (Lifecycle) getSource();}/*** @return the event type of this event.*/public String getType() {return this.type;}
}

 事件监听器接口:

java">public interface LifecycleListener {/*** Acknowledge the occurrence of the specified event.** @param event LifecycleEvent that has occurred*/void lifecycleEvent(LifecycleEvent event);}

 事件监听管理类LifecycleBase:

java">public abstract class LifecycleBase implements Lifecycle {/*** The list of registered LifecycleListeners for event notifications.*/private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();@Overridepublic void addLifecycleListener(LifecycleListener listener) {lifecycleListeners.add(listener);}@Overridepublic LifecycleListener[] findLifecycleListeners() {return lifecycleListeners.toArray(new LifecycleListener[0]);}@Overridepublic void removeLifecycleListener(LifecycleListener listener) {lifecycleListeners.remove(listener);}/*** Allow sub classes to fire {@link Lifecycle} events.** @param type  Event type* @param data  Data associated with event.*/protected void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(this, type, data);for (LifecycleListener listener : lifecycleListeners) {listener.lifecycleEvent(event);}}protected synchronized void setState(LifecycleState state) throws LifecycleException {setStateInternal(state, null, true);}private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)throws LifecycleException {...this.state = state;String lifecycleEvent = state.getLifecycleEvent();if (lifecycleEvent != null) {fireLifecycleEvent(lifecycleEvent, data);}}
}

事件源,例如StandardSever类,开启的时候,调用setState()方法设置状态,继续调用到LifecycleBase.setStateInternal()方法,最后就会让相关监听器进行处理:

java">public final class StandardServer extends LifecycleMBeanBase implements Server {/*** Global naming resources.*/private NamingResourcesImpl globalNamingResources = null;/*** The naming context listener for this web application.*/private final NamingContextListener namingContextListener;/*** Start nested components ({@link Service}s) and implement the requirements of* {@link org.apache.catalina.util.LifecycleBase#startInternal()}.** @exception LifecycleException if this component detects a fatal error that prevents this component from being*                                   used*/@Overrideprotected void startInternal() throws LifecycleException {...setState(LifecycleState.STARTING);...}
}


http://www.ppmy.cn/ops/134684.html

相关文章

从客户需求视角去认识ZLG | 边缘计算网关多种应用

在工业领域&#xff0c;串行总线与EtherNET总线广泛应用&#xff0c;物联网的兴起带来众多智能应用。尽管应用多样&#xff0c;但底层技术逻辑却殊途同归&#xff0c;本文将介绍ZLG致远电子串行总线和EtherNET总线之间的联动应用。 本文将从系统集成需求出发&#xff0c;以ZLG致…

第九章 DIV+CSS布局

9.1 DIVCSS概述 9.1.1 认识DIV CSS前面几章节都有打&#xff0c;此处就不多说&#xff0c;DIV也是之前有经常用到盒子。 9.1.2 DIV的宽高设置 9.1.2.1 宽高属性 9.1.2.2 div标签内直接设置宽高 9.1.2.3 div使用选择器设置宽高 <!DOCTYPE html> <html><he…

SwiftUI开发教程系列 - 第十二章:本地化与多语言支持

随着应用程序的全球化需求增加&#xff0c;为了方便不同地区的用户&#xff0c;支持多语言和本地化变得越来越重要。SwiftUI 为开发者提供了便捷的本地化方法&#xff0c;让应用能够根据用户的设备语言自动适配。 12.1 本地化的基本概念 本地化&#xff08;Localization&…

以太坊基础知识结构详解

以太坊的历史和发展 初创阶段 2013年&#xff1a;Vitalik Buterin 发表了以太坊白皮书&#xff0c;提出了一个通用的区块链平台&#xff0c;不仅支持比特币的货币功能&#xff0c;还能支持更复杂的智能合约。2014年&#xff1a;以太坊项目启动&#xff0c;进行了首次ICO&…

Mock.js生成随机数据,拦截 Ajax 请求

Mock.js 是一个用于模拟数据的 JavaScript 库&#xff0c;特别适合用于前端开发过程中生成假数据进行接口测试。它可以拦截 Ajax 请求并生成随机数据&#xff0c;还可以模拟服务器的响应来加速前端开发。 一、安装 Mock.js 可以通过以下几种方式引入 Mock.js&#xff1a; CDN…

《操作系统 - 清华大学》4 -1:非连续内存分配:分段

文章目录 0. 概述1. 为什么需要非连续内存分配2.分段3. 分段寻址方案4. 硬件方案 0. 概述 首先要考虑的一个问题就是为什么要用非连续内存来管理现在物理内存。当前具有的非连续物理内存的管理方法&#xff0c;主要涉及到的分段和分页这两种方式。以及关于分页中的一种很重要的…

《Django 5 By Example》阅读笔记:p54-p75

《Django 5 By Example》学习第3天&#xff0c;p54-p75总结&#xff0c;总计22页。 一、技术总结 1.分页 (1)分页&#xff1a;Paginator (2)页数不存在处理&#xff1a; EmptyPage, PageNotAnInteger 2.class-based views(类视图) (1)为什么使用类视图&#xff1f; 1)Or…

web安全漏洞之ssrf入门

web安全漏洞之ssrf入门 1.什么是ssrf SSRF(Server Side Request Forgery,服务端请求伪造)是一种通过构造数据进而伪造成服务端发起请求的漏洞。因为请求是由服务器内部发起&#xff0c;所以一般情况下SSRF漏洞的目标往往是无法从外网访问的内系统。 SSRF漏洞形成的原理多是服务…