Tomcat源码篇-生命周期的架构设计

网友投稿 668 2022-11-22

Tomcat源码篇-生命周期的架构设计

Tomcat源码篇-生命周期的架构设计

Tomcat生命周期

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

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

一、LifeCycle接口设计

1.生命周期的方法

2.相关的状态处理

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

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

二、-和事件的设计

接下来看下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; }}

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

三、LifecycleBase

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

1.事件处理

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

// 存储了所有的实现了LifecycleListener接口的- private final List 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); } }

&emsp已经针对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); }

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的启动流程来带领大家一起查看。下一篇给大家介绍。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:阿里二面JVM相关面试题
下一篇:Spring源码BeanFactoryPostProcessor详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~