Tomcat生命周期详解

目录
  • 引言
  • 1、LifeCycle接口设计
    • 1.1 生命周期的方法
    • 1.2 相关的状态处理
  • 2.监听器和事件的设计
  • 3.LifecycleBase
    • 3.1 事件处理
    • 3.2 生命周期方法

引言

在上篇文章中我们看到了Tomcat架构中的核心组件,而且各个组件都有各自的作用,各司其职,而且相互之间也有对应的父子关系,那么这些对象的创建,调用,销毁等操作是怎么处理呢?

也就是在Tomcat中的组件的对象生命周期是怎么管理的呢?针对这个问题,在Tomcat中设计了Lifecycle接口来统一管理Tomcat中的核心组件的生命周期,所以本文我们就系统的来介绍下Lifecycle接口的设计

1、LifeCycle接口设计

为了统一管理Tomcat中的核心组件的生命周期,而专门设计了LifeCycle接口来统一管理,我们来看看在LifeCycle接口中声明了哪些内容。

1.1 生命周期的方法

在LifeCycle中声明了和生命周期相关的方法,包括init(),start(),stop(),destory()等方法。

在声明的方法执行的过程中会涉及到对应的状态的转换,在LifeCycle接口的头部文档中很清楚的说了。

1.2 相关的状态处理

通过上图我们可以很清楚的看到相关的方法执行会涉及到的相关状态的转换,比如init()会从New这个状态开始,然后会进入 INITIALIZING 和 INITIALIZED 等。因为这块涉及到了对应的状态转换,在Lifecycle中声明了相关的状态和事件的生命周期字符串。

    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";
    /**
     * The LifecycleEvent type for the "periodic" event.
     * 周期性事件(后台线程定时执行一些事情,比如:热部署、热替换)
     */
    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";

在LifecycleState中建立了对应关系

针对特定的事件就会有相关的监听器来监听处理。在Lifecycle中定义了相关的处理方法。

    public void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);

通过方法名称我们就能很清楚该方法的相关作用,就不过程介绍了。然后来看下对应的监听器和事件接口的对应设计。

2.监听器和事件的设计

接下来看下LifecycleListener的设计。其实代码非常简单。

public interface LifecycleListener {
    /**
     * Acknowledge the occurrence of the specified event.
     *  触发监听器后要执行逻辑的方法
     * @param event LifecycleEvent that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event);
}

然后来看下事件的接口

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;
    }
}

也是非常简单,不过多的赘述。

3.LifecycleBase

通过上面的介绍我们可以看到在Tomcat中设计了Lifecycle和LifecycleListener和LifecycleEvent来管理核心组件的生命周期,那么我们就需要让每一个组件都实现相关的接口。这时你会发现交给子类的工作量其实是比较大的,不光要完成各个组件的核心功能,还得实现生命周期的相关处理,耦合性很强,这时在Tomcat中给我们提供了一个LifecycleBase的抽象类,帮助我们实现了很多和具体业务无关的处理,来简化了具体组件的业务。

3.1 事件处理

在上面的接口设计中对于监听对应的事件处理是没有实现的,在LifecycleBase把这块很好的实现了,我们来看下。首先定义了一个容器来存储所有的监听器

// 存储了所有的实现了LifecycleListener接口的监听器
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

同时提供了触发监听的相关的方法,绑定了对应的事件。

    /**
     * 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);
        }
    }

已经针对Listener相关的处理方法

    // 添加监听器
    @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);
    }

3.2 生命周期方法

在LifecycleBase中最核心的还是实现了Lifecycle中的生命周期方法,以init方法为例我们来看。

    /**
     * 实现了 Lifecycle 中定义的init方法
     * 该方法和对应的组件的状态产生的关联
     * @throws LifecycleException
     */
    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            // 无效的操作  只有状态为 New 的才能调用init方法进入初始化
            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());
        }
    }

源码解析:

  • 我们看到首先会判断当前对象的state状态是否为NEW,因为init方法只能在NEW状态下才能开始初始化
  • 如果1条件满足则会更新state的状态为 INITIALIZED 同时会触发这个事件
  • 然后initInternale()方法会交给子类具体去实现,
  • 等待子类处理完成后会把状态更新为 INITIALIZED

我们可以进入setStateInternal方法查看最后的关键代码:

        // ....
        this.state = state; // 更新状态
        // 根据状态和事件的绑定关系获取对应的事件
        String lifecycleEvent = state.getLifecycleEvent();
        if (lifecycleEvent != null) {
            // 发布对应的事件
            fireLifecycleEvent(lifecycleEvent, data);
        }

可以看到和对应的事件关联起来了。init方法的逻辑弄清楚后,你会发现start方法,stop方法,destory方法的处理逻辑都是差不多的,可自行观看。

而对应的 initInternal()方法的逻辑我们需要在 Server Service Engine Connector等核心组件中再看,这个我们会结合Tomcat的启动流程来带领大家一起查看。

以上就是Tomcat生命周期详解的详细内容,更多关于Tomcat生命周期的资料请关注我们其它相关文章!

(0)

相关推荐

  • maven插件spring-boot-starter-tomcat的使用方式

    目录 tomcat内嵌到web项目中 1.pom.xml 配置 2.tomcat使用maven内嵌入到web项目需要jdk运行环境 3.springmvc依赖 4.编写表现层代码 5.配置web.xml 6.SpringMVC的配置文件 7.配置完成后在项目上鼠标右键 tomcat内嵌到web项目中 将tomcat 内嵌到 web项目中,这样可以直接运行 webapp项目. 不需要再部署到额外的tomcat,直接就可以运行了. 1.pom.xml 配置 <plugins> <plugin

  • Nginx反向代理转发tomcat的实现

    刚刚接触Nginx,记录下学习过程 先说正向代理,比如要访问youtube,但是不能直接访问,只能先找个翻墙软件,通过翻墙软件才能访问youtube. 翻墙软件就叫做正向代理. 所谓的反向代理,指的是用户要访问youtube,但是youtube悄悄地把这个请求交给bilibili来做,那么bilibili就是反向代理了. 在当前教程指的就是访问nginx,但是nginx把请求交给tomcat来做. 安装tomcat 参考文章:https://www.jb51.net/article/137839

  • Tomcat启动核心流程示例详解

    目录 一.Tomcat的启动核心流程 1.启动的入口 2.init方法 3.load方法 4.start方法 5.核心流程的总结 一.Tomcat的启动核心流程 前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法. 1.启动的入口 你可以通过脚本来启动Tomcat服务(startup.bat),但如果你看过脚本的命令,你会发现最终调用的还是Boot

  • Tomcat日志自动分割的三种方法

    目录 1.方法一:使用 cronolog 2.方法二:使用 rotatelogs 3.方法三:使用脚本 修改前的 tomcat 都是将所有数据保存在一个日志文件 catalina.out 中,平时实验环境下没有什么问题,但是在生产环境中,由于数据量巨大,会导致日志查看困难,因此将日志通过某些方法进行自动分割,而修改后的 tomcat 将会按“日”保存日志文件,文件格式例如:catalina.2022-6-10.out 1.方法一:使用 cronolog 官网:http://cronolog.or

  • Tomcat服务器配置https认证(使用keytool生成证书)

    目录 一.证书生成 二.证书使用 一.证书生成 1 .生成服务器证书 (1)打开打开命令控制台,进入jdk的bin目录 (2)keytool为Tomcat生成证书(“-validity 36500”证书有效期,36500表示100年,默认值是90天) keytool -genkey -v -alias tomcat -keyalg RSA -keystore C:\MyFile\work_tools\apache-tomcat-8.5.55\apache-tomcat-8.5.55\tomcat

  • Tomcat安装shell脚本的方法步骤

    目录 一.JAVA环境安装 二.JAVA环境安装检测 三.tomcat安装与启动 四.tomcat启动检测 五.脚本程序 六.执行效果检验 今天继续给大家介绍Linux运维相关知识,本文主要内容是Tomcat安装shell脚本(假设我们已经下载下来了JAVA和Tomcat的安装包). 一.JAVA环境安装 首先,要安装Tomcat,我们就必须安装JAVA环境.JAVA环境的安装需要解压JAVA的安装包,并且设置JAVA的环境变量,相关脚本如下所示: tar xf jdk-8u45-linux-x

  • Tomcat生命周期详解

    目录 引言 1.LifeCycle接口设计 1.1 生命周期的方法 1.2 相关的状态处理 2.监听器和事件的设计 3.LifecycleBase 3.1 事件处理 3.2 生命周期方法 引言 在上篇文章中我们看到了Tomcat架构中的核心组件,而且各个组件都有各自的作用,各司其职,而且相互之间也有对应的父子关系,那么这些对象的创建,调用,销毁等操作是怎么处理呢? 也就是在Tomcat中的组件的对象生命周期是怎么管理的呢?针对这个问题,在Tomcat中设计了Lifecycle接口来统一管理Tom

  • servlet配置方法及其生命周期详解

    servlet配置: 在web.xml中,首先向服务器注册一个servlet.在<servlet>标签下 给定一个servlet名字,这个servlet-name是我们自己用的,方便我们用它对servlet进行配置. 1 <servlet-name>AServlet</servlet-name>然后指定一个全类名,这个是给服务器使用,服务器用来创建全类名对象的实例 1 <servlet-class>com.servlet.AServlet</servl

  • 基于Listener监听器生命周期(详解)

    一.Listener生命周期 listener是web三大组件之一,是servlet监听器,用来监听请求,监听服务端的操作. listener分为:(都是接口类,必须实现相应方法) 1.生命周期监听器(3个) ServletContextListener requestDestroyed 在容器启动时被调用(在servlet被实例化前执行) requestInitialized 在容器销毁时调用(在servlet被销毁后执行) HttpSessionListener sessionCreated

  • JavaWEB中Servlet的生命周期详解

    目录 一.什么是Servlet 生命周期? 二.Servlet 是由谁来维护的? 三.Servlet 对象 是什么时候创建的? 四.测试 Tomcat 什么时候被销毁? 总结 一.什么是Servlet 生命周期? Servlet 对象什么时候被创建? Servlet对象什么时候被销毁? Servlet 对象创建了几个? Servlet 对象的声明周期表示:Servlet 对象从出生到销毁的过程是怎样的 二.Servlet 是由谁来维护的? Servlet 是由 Tomcat 服务器全权负责的,程

  • Java中Servlet的生命周期详解

    目录 Web基础和HTTP协议 什么是Servlet Servlet的生命周期 Web基础和HTTP协议 ┌─────────┐ ┌─────────┐ │░░░░░░░░░│ │O ░░░░░░░│ ├─────────┤ ├─────────┤ │░░░░░░░░░│ │ │ ├─────────┤ │ │ │░░░░░░░░░│ └─────────┘ └─────────┘ │ request 1 │ │─────────────────────>│ │ request 2 │ │───

  • Spring配置使用之Bean生命周期详解

    基本概念 Spring 中的 Bean 的生命周期,指的是 Bean 从创建到销毁的过程. 下面来探究下几个有关 Bean 生命周期配置的属性. lazy-init lazy-init 表示延迟加载 Bean,默认在 Spring IoC 容器初始化时会实例化所有在配置文件定义的 Bean,若启用了 lazy-init 则在调用 Bean 时才会去创建 Bean. 定义 Bean: public class Animals { public Animals(){ System.out.print

  • 基于asp.net MVC 应用程序的生命周期(详解)

    首先我们知道http是一种无状态的请求,他的生命周期就是从客户端浏览器发出请求开始,到得到响应结束.那么MVC应用程序从发出请求到获得响应,都做了些什么呢? 本文我们会详细讨论MVC应用程序一个请求的生命周期,从一个控件到另一个控件是怎样被处理的.我们还会详细介绍一下整个请求的生命周期中,用到的相关组件.因为在平常的开发过程中,我们可能知道怎样去使用MVC框架来处理相关的请求,大部分的时候我们只是在controller和action方法之间做相关的处理,对于真正内在的运行机制可能不是很了解.其实

  • Android入门教程之组件Activity的生命周期详解

    目录 返回栈 Activity 状态 1. 运行状态 2. 暂停状态 3. 停止状态 4. 销毁状态 Activity 的生存期 onCreate() onStart() onResume() onPause() onStop() onDestroy() onRestart() 完整生存期 可见生存期 前台生存期 Activity 回收处理 返回栈 Android 中的 Activity 是可以层叠的,我们每启动一个新的 Activity,就会覆盖在原有的 Activity 之上,然后点击 Ba

  • Java开发学习之Bean的生命周期详解

    目录 一.什么是生命周期 二.环境准备 三.生命周期设置 步骤1:添加初始化和销毁方法 步骤2:配置生命周期 步骤3:运行程序 四.close关闭容器 五.注册钩子关闭容器 六.bean生命周期总结 一.什么是生命周期 首先理解下什么是生命周期? 从创建到消亡的完整过程,例如人从出生到死亡的整个过程就是一个生命周期. bean生命周期是什么? bean对象从创建到销毁的整体过程. bean生命周期控制是什么? 在bean创建后到销毁前做一些事情. 二.环境准备 环境搭建: 创建一个Maven项目

  • Java开发学习之Bean的作用域和生命周期详解

    目录 一.Bean 的作用域 二.Spring 的执行流程 三.Bean 的生命周期 一.Bean 的作用域 在之前学习Java基础的时候,有接触到作用域这样的概念.一个变量并不一定在任何区域都是有效的,限定这个变量的可用性的代码范围就是该变量的作用域. 但是在这里 Bean 的作用域的概念和以前所认为的作用域有所不同. Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式. 接下来,将会举一个案例来讲讲什么是作用域,什么是行为模式 案例概要: 创建一个共有的 Bean

随机推荐