文档章节

【杂谈】Tomcat 之 Lifecycle接口

o
 osc_w9s1w4o0
发布于 2019/04/01 22:49
字数 1204
阅读 9
收藏 0

精选30+云产品,助力企业轻松上云!>>>

前言

  此篇随笔记录《How Tomcat works》中关于Lifecycle接口的相关总结

Lifecycle接口的主要目的

核心:统一。

已知Tomcat的卡特琳娜(Catalina)由许多组件构成。当Catalina启动的时候,这些组件也要跟着一起启动,并且当Catalina关闭的时候,这些组件也要同时关闭,并且要进行必要的清理操作,释放资源。例如,当容器关闭的时候,需要调用已加载的servlet对象的destroy方法,session对象也要持久化到secondary storage(二级存储,通常指的就是硬盘)。这就要求所有Component有一致的方法,可以统一处理。

如果没有统一会怎么样?

其实也不会怎么样,就是编程起来就比较麻烦。比如有的对象初始化方法叫initiate,有的又叫init。用都可以用,就是不太好用,即你要记住这个对象的初始化方法到底叫什么。而统一之后呢,可以放到一个List中,遍历调用。这不就方便多了嘛。

Lifecycle的事件与监听

Lifecycle,翻译过来就是“生命周期”。那生命周期变化,从一个生命周期进入另一个生命周期,自然就会有相应的事件来表示。比如,人从幼儿长大成人,这是一个事件“成长”,而从中年步入老年,又是另外一个事件“衰老”。那么既然有事件的触发,那就会有事件的监听处理,常见的有两大种。

Lifecycle事件监听器原理

其实就是观察者模式了,熟悉的人就不用看了。关联的类清单如下:

  • LifecycleEvent(事件对象)
  • Lifecycle 接口
  • LifecycleListener 接口
  • LifecycleBase => 用于存储并触发监听器,《How Tomcat works》里是比较旧的,对应的是LifecycleSupport类

(1)LifecycleEvent

LifecycleEvent继承于EventObject,EventObject是JDK提供的,它只有一个字段,即Object类型的source,用于表示事件的产生者。

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;

    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }

    public Object getSource() {
        return source;
    }

    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}
public final class LifecycleEvent extends EventObject {

    private static final long serialVersionUID = 1L;


    /**
     * 
     *
     * @param lifecycle 指明当前事件在哪个lifecycle组件上产生
     * @param type Event type 事件类型
     * @param data Event data 额外的数据
     */
    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
        //把lifecycle赋给source
        super(lifecycle);
        this.type = type;
        this.data = data;
    }


    /**
     *  与此事件关联的事件数据
     */
    private final Object data;


    /**
     * 事件类型
     */
    private final String type;


    public Object getData() {
        return data;
    }

    public Lifecycle getLifecycle() {
        return (Lifecycle) getSource();
    }

    public String getType() {
        return this.type;
    }
}

(2)Lifecycle接口

public interface Lifecycle { 

    //统一的事件类型
    public static final String BEFORE_INIT_EVENT = "before_init";
    public static final String AFTER_INIT_EVENT = "after_init";
    public static final String START_EVENT = "start";
    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";
    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";

    //lifecycle表示的是一个组件,故可以在组件上添加监听器
    public void addLifecycleListener(LifecycleListener listener);

    //获取注册在此组件上的监听器
    public LifecycleListener[] findLifecycleListeners();

    //移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);

    //统一的生命周期方法
    public void init() throws LifecycleException;

    public void start() throws LifecycleException;

    public void stop() throws LifecycleException;

    public void destroy() throws LifecycleException;

    //获取组件状态
    public LifecycleState getState();

    public String getStateName();

    public interface SingleUse {
    }
}

(3)LifecycleListener接口

public interface LifecycleListener {

    //接收事件对象作为参数
    //在方法体内,根据事件类型做自定义的响应
    public void lifecycleEvent(LifecycleEvent event);

}

(4)LifecycleBase 抽象类

一般组件都以此为父类。主要看存监听器的List和fireLifecycleEvent方法。以下把大部分代码省略了,感兴趣的可自行翻阅源码。

public abstract class LifecycleBase implements Lifecycle {

    private static final Log log = LogFactory.getLog(LifecycleBase.class);

    private static final StringManager sm = StringManager.getManager(LifecycleBase.class);

    //用于存储注册在此组件上的监听器
    private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

    //组件状态
    private volatile LifecycleState state = LifecycleState.NEW;


    private boolean throwOnFailure = true;

    public boolean getThrowOnFailure() {
        return throwOnFailure;
    }

    public void setThrowOnFailure(boolean throwOnFailure) {
        this.throwOnFailure = throwOnFailure;
    }


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


    //触发事件,告知所有监听器。
    protected void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(this, type, data);
        for (LifecycleListener listener : lifecycleListeners) {
            listener.lifecycleEvent(event);
        }
    }


    @Override
    public final synchronized void init() throws LifecycleException {
        //...省略
    }

    protected abstract void initInternal() throws LifecycleException;


    @Override
    public final synchronized void start() throws LifecycleException {
        //...省略
    }

    protected abstract void startInternal() throws LifecycleException;


    @Override
    public final synchronized void stop() throws LifecycleException {
        //...省略
    }


    protected abstract void stopInternal() throws LifecycleException;


    @Override
    public final synchronized void destroy() throws LifecycleException {
        //...省略
    }


    protected abstract void destroyInternal() throws LifecycleException;

    @Override
    public LifecycleState getState() {
        return state;
    }


    @Override
    public String getStateName() {
        return getState().toString();
    }

    protected synchronized void setState(LifecycleState state) throws LifecycleException {
        setStateInternal(state, null, true);
    }

    protected synchronized void setState(LifecycleState state, Object data)
            throws LifecycleException {
        setStateInternal(state, data, true);
    }


    private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
            throws LifecycleException {

        //...省略
    }


    private void invalidTransition(String type) throws LifecycleException {
        //...省略
    }


    private void handleSubClassException(Throwable t, String key, Object... args) throws LifecycleException {
        //...省略
    }
}

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
浅析Tomcat之Lifecycle

Tomcat很多组件都有其生命周期,比如:StandardServer,StandardService等.这个生命周期用来控制组件的资源情况.在Tomcat的生命周期管理中主要体现在接口Lifecycle,LifecycleListener及其相关类...

D_GrayMan
2016/07/05
19
0
深入理解Tomcat系列之一:系统架构

前言 Tomcat是Apache基金组织下的开源项目,性质是一个Web服务器。下面这种情况很普遍:在eclipse床架一个web项目并部署到Tomcat中,启动tomcat,在浏览器中输入一个类似的url,然后就可以看...

Henrykin
2016/10/13
21
0
tomcat的启动过程与Lifecycle

本文主要介绍tomcat启动过程中,从server到context这一部分,主要涉及Lifecycle。 public interface Lifecycle { } 上面是Lifecycle接口,我把注释都去掉了,接口定义中开始部分的static域(...

元圈
2012/07/14
1.6K
0
《How Tomcat Works》读书笔记(七)Logger

Logger是一个用来记录消息的tomcat组件并和一个container绑定在一起。 看一下它的接口定义: public interface Logger { //绑定容器 //日志级别 public int getVerbosity(); //当传入的日志级...

奋斗的海贼
2013/02/18
330
0
Tomcat8源码笔记(一)Lifecycle接口

第一次阅读Tomcat8源码,就以Lifecycle作为笔记阅读的开篇吧,一千个读者就有一千个哈姆雷特,每个人都Tomcat的理解都不同,如果不记录一次Tomcat源码可能忘了就忘了. 断断DEBUG了几天,决定...

osc_7c6h7z9p
2019/04/05
2
0

没有更多内容

加载失败,请刷新页面

加载更多

为什么从HBase的0.96版本开始,舍弃了-ROOT-文件?

HBase结构的读写流程 (1). HBase0.96版本之前: (2). HBase0.96开始: a. 当客户端获取到.meta文件的位置之后,会缓存.meta.文件的位置 b. 客户端还会缓存HRegion的位置 -ROOT-存在的意义: ...

其乐m
21分钟前
12
0
volatile关键字对 - What is the volatile keyword useful for

问题: At work today, I came across the volatile keyword in Java. 今天的工作中,我遇到了Java中的volatile关键字。 Not being very familiar with it, I found this explanation: 不太熟......

技术盛宴
26分钟前
25
0
golang 封装 mysql 和 redis 连接

Mysql封装 package dbimport ("fmt"_ "github.com/go-sql-driver/mysql""github.com/jmoiron/sqlx")var DB *sqlx.DBfunc init(){database, err := sqlx.Op......

开源中国最牛的人
27分钟前
16
0
pdfbox 读取文件报错 java.io.IOException: Page tree root must be a dictionary

pdfbox java.io.IOException: Page tree root must be a dictionary 示例代码 public static void main(String[] args) { try (InputStream sampleInputs = new ClassPathResource("s......

lemos
35分钟前
28
0
整理 Linux下列出目录内容的命令

在 Linux 中,有非常多的命令可以让我们用来执行各种各样的任务。当我们想要像使用文件浏览器一样列出一个目录下的内容时,大家第一时间想到的是 ls 命令。但只有 ls 命令能实现这个目的吗?...

良许Linux
36分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部