Tomcat-Tomcat生命周期

简介: Tomcat-Tomcat生命周期

一、Tomcat生命周期


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


image.png

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



1、LifeCycle接口设计


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


1.1 生命周期的方法



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

image.png


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


image.png

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中建立了对应关系

image.png


  针对特定的事件就会有相关的监听器来监听处理。在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的抽象类,帮助我们实现了很多和具体业务无关的处理,来简化了具体组件的业务。


image.png

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());
        }
    }
复制代码


源码解析:


  1. 我们看到首先会判断当前对象的state状态是否为NEW,因为init方法只能在NEW状态下才能开始初始化


  1. 如果1条件满足则会更新state的状态为 INITIALIZED 同时会触发这个事件


  1. 然后initInternale()方法会交给子类具体去实现,


  1. 等待子类处理完成后会把状态更新为 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的启动流程来带领大家一起查看。下一篇给大家介绍。



相关文章
|
4月前
|
设计模式 人工智能 安全
【Tomcat源码分析】生命周期机制 Lifecycle
Tomcat内部通过各种组件协同工作,构建了一个复杂的Web服务器架构。其中,`Lifecycle`机制作为核心,管理组件从创建到销毁的整个生命周期。本文详细解析了Lifecycle的工作原理及其方法,如初始化、启动、停止和销毁等关键步骤,并展示了LifecycleBase类如何通过状态机和模板模式实现这一过程。通过深入理解Lifecycle,我们可以更好地掌握组件生命周期管理,提升系统设计能力。欢迎关注【码上遇见你】获取更多信息,或搜索【AI贝塔】体验免费的Chat GPT。希望本章内容对你有所帮助。
|
设计模式 前端开发 应用服务中间件
拆解Tomcat10: (六) 核心组件的生命周期管理与组合模式解析(二)
上一篇《拆解Tomcat10 (五) 核心组件的初始化与设计模式解析》分享了Tomcat的核心组件的是如何实现生命周期接口的,以及生命周期方法的调用逻辑。如果把Tomcat比作一台机器,那么这台机器是如何开机、关机的呢? 当按下开机键,所有核心组件会逐步初始化、启动;当按下关机键,所有组件又会随着关机,释放资源,这是如何实现的呢?
1081 0
拆解Tomcat10: (六) 核心组件的生命周期管理与组合模式解析(二)
|
设计模式 XML 算法
拆解Tomcat10: (六) 核心组件的生命周期管理与组合模式解析(一)
上一篇《拆解Tomcat10 (五) 核心组件的初始化与设计模式解析》分享了Tomcat的核心组件的是如何实现生命周期接口的,以及生命周期方法的调用逻辑。如果把Tomcat比作一台机器,那么这台机器是如何开机、关机的呢? 当按下开机键,所有核心组件会逐步初始化、启动;当按下关机键,所有组件又会随着关机,释放资源,这是如何实现的呢?
836 0
拆解Tomcat10: (六) 核心组件的生命周期管理与组合模式解析(一)
|
Java 应用服务中间件
面试官:既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?
上一次的文章中,阿粉在面试官面前说了对启动流程不太理解,然后和他聊了一会,然后他又提出了你既然不是特别了解启动流程的话,那你对Tomcat的生命周期熟悉么?
面试官:既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?
|
设计模式 应用服务中间件 容器
Tomcat的生命周期管理
Tomcat的生命周期管理
151 0
Tomcat的生命周期管理
|
Java 应用服务中间件 容器
|
Java 应用服务中间件 容器
Tomcat7.0源码分析——生命周期管理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/51473807 前言  从server.xml文件解析出来的各个对象都是容器,比如:Server、Service、Connector等。
1019 0
|
Java 应用服务中间件 容器
TOMCAT源码分析——生命周期管理(一)
前言   从server.xml文件解析出来的各个对象都是容器,比如:Server、Service、Connector等。这些容器都具有新建、初始化完成、启动、停止、失败、销毁等状态。tomcat的实现提供了对这些容器的生命周期管理,本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程。
4462 0
|
应用服务中间件 容器
tomcat生命周期的管理——生命周期统一接口Lifecycle
我们知道Tomcat的架构设计是清晰的、模块化的,其拥有很多组件,假如我们要启动Tomcat,可以一个一个启动组件,但这样启动有很多缺点,不仅麻烦,而且容易漏了组件启动,还会对后面动态组件扩展带来麻烦。
899 0