前言

  此篇随笔记录《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 {
//...省略
}
}

【杂谈】Tomcat 之 Lifecycle接口的更多相关文章

  1. Tomcat8源码笔记(一)Lifecycle接口

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

  2. 0001 - Spring 框架和 Tomcat 容器扩展接口揭秘

    前言 在 Spring 框架中,每个应用程序上下文(ApplicationContext)管理着一个 BeanFactory,BeanFactory 主要负责 Bean 定义的保存.Bean 的创建. ...

  3. 本地tomcat调用远程接口报错:java.lang.reflect.InvocationTargetException

    今天碰到一个奇怪的问题,本地Eclipse起了一个tomcat通过http去调一个外部接口,结果竟然报了一个反射的异常,先看下完整日志: , :: 下午 org.apache.catalina.sta ...

  4. java web项目war包部署,使用tomcat对指定接口设置身份认证

    先简单说一下需求: 将一个基于springboot2.0开发的java web项目打成war包,通过tomcat部署到一台linux服务器上,项目相关的一些图片等资源也按照一定规则放置在服务器构建好的 ...

  5. IDEA部署Tomcat应用所有接口中文乱码

    解决问题的思路: 1.分析比对http请求头,contentType等设置 2.前段编码,后端解码,这个方式比较落麻烦,凡是有中文乱码的地方都要进行解决 3.修改Tomcat的默认编码,tomcat8 ...

  6. 怎么用tomcat对socket接口的程序进行调试

    对socket(套接字)的demo方法大多都是用main方法进行测试的,那如何用tomcat进行测试呢? 这里需要借助一个工具:工具的名字是:Sockettool.exe .下图是该工具的内容.连上监 ...

  7. 浅谈Tomcat和Servlet

    本文浅谈下对Tomcat和Servlet总体的理解,初学时有用过一段时间,但当时疲于应对如何xml配置和使用,对他们的理解就像是一个黑匣子.现在回顾一下帮助自己加深网络的理解.开始还是先推荐我看的文章 ...

  8. 深入分析理解Tomcat体系结构

    Tomcat整体结构 由上图可知Tomcat的顶层容器是Server,而且一个Tomcat对应一个Server,一个server有多个service提供服务.service包含两个重要组件:Conne ...

  9. Tomcat源码分析 (七)----- Tomcat 启动过程(二)

    在上一篇文章中,我们分析了tomcat的初始化过程,是由Bootstrap反射调用Catalina的load方法完成tomcat的初始化,包括server.xml的解析.实例化各大组件.初始化组件等逻 ...

随机推荐

  1. select下拉框左右变换

    效果图: 使用jQuery插件---multiselect2side做法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...

  2. python语言相关语法基础

    numpy系列import numpya = numpy.array([[1,2], [3,4]])b = numpy.array([[5,6], [7,8]])a*b>>>arra ...

  3. vuex的getters处理数据

    getters是用来处理state里的数据的 getters传递一个值state 例子: store.js import Vue from 'vue' import Vuex from 'vuex' ...

  4. 添加sqljdbc的maven依赖JAVA环境配置

    sqljdbc是微软sql server的jdbc驱动 使用sqljdbc需要从微软的官方网站下载jar包: http://www.microsoft.com/en-us/download/detai ...

  5. index.php入口文件至根目录

      登录|注册       咖啡如同生活的专栏 从不羡慕别人的优秀,因为相信自己也可以优秀. 闲下来时看看书,书本里的故事,总有你学到的人生.       目录视图 摘要视图 订阅 异步赠书:9月重磅 ...

  6. UML-Based Modeling of Robustness Testing

    一.基本信息 标题:UML-Based Modeling of Robustness Testing 时间:2014 出版源:IEEE会议论文 领域分类:稳健性测试:UML测试Prole:UML Pr ...

  7. Java程序CPU使用率过高

    Java程序CPU使用率过高 通过top命令找到使用率过高的java进程PID 根据进程号查找线程TID:ps -mp PID -o THREAD,tid,time 将TID转换成16进制:print ...

  8. cordova 开发

    这个挺好用的, 确实 把一个 Android 和 IOS 的App 给生成了. html为前端, js调用 Java 或 object -C的代码. 加快了开发的进度 在不使用插件的基础上 ,基本实现 ...

  9. List、Set、数据结构、Collections

    一.数据结构: 1.什么是数据结构: 一种数据的存储方式 2.常见的4+1种数据结构 堆栈结构: 它是只有一个开口的容器结构 特点: 先进后出(FILO) 例子:弹夹,桶装可比克 队列结构: 它是两端 ...

  10. Python之路【第一篇】Linux常见命令语句

    查看当前目录:        pwd 查看文件具体大小: ls -l 返回上一级: cd.. 返回根目录:     cd / 创建一个隐藏文件:    vim .test 显示隐藏文件:      l ...