最近在阅读“how tomcat works”这本书,结合tomcat7的源码进行学习。对于学习的收获,将通过“tomcat学习系列”记录下来,和大家一起分享和交流,也算对自己学习的一种促进。闲话不多说,正文开始。 
    Catalina内部由多个组件组成,启动时各个组件都需要启动,关闭时需要各个组件关闭。如何协作各个组件的初始化、启动、停止、销毁等的一致性,通过各组件实现Lifecycle这个接口来完成。各组件在启动、关闭等重要生命周期中,会发出事件通知,通知已注册的观察者做事件处理。

一、主要类图

二、主要类介绍

1) Lifecycle 
Lifecycle表示生命周期概念的接口。定义了组件生命周期中的通用事件(START_EVENT、STOP_EVENT等)和接口(start、stop、destroy、addLifecycleListener、removeLifecycleListener等)。组件可以通过实现Lifecyecle接口,完成组建的重要生命周期实现和组建的观察者管理。 
2)LifecycleState 
组件的有效状态枚举。定义了组件生命周期中的状态和状态对应的事件。当状态发生改变时,会发出相应事件,通知观察者进行处理。 
3)LifecycleBase 
Lifecycle接口的抽象的基础实现类,主要实现了制定启动和停止状态相关的转换规则。Lifecycle接口的默认实现,实现init、start、stop、destroy等方法。对观察者的增加、查找和删除等操作会适配器方式,由组合的LifecycleSupport实例来完成。此外还提供了生成LifecycleEvent事件的接口 
4)LifecycleSupport 
用来帮助传送消息给监听器的辅助类。观察者的实际管理类,实现观察者的注册、删除、查询、调用等操作。 
5)LifecycleListener 
用来监听组件状态变化并触发相应事件的监听器。生命周期的观察者,定义了观察者的事件处理接口lifecycleEvent(LifecycleEvent event)。 
6)ServerLifecycleListener 
实际的观察者,实现了事件处理接口。 
7)LifecycleEvent 
组件状态变化时触发的事件。观察者使用的参数,它封装了事件来源、事件类型和事件数据,使得观察者可以按事件来源和事件类型分类处理事件。

8)LifecycleException

生命周期相关异常。

三、下面分别对这几个类进行解析

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

实现了Lifecycle接口的非常之多,具体可以去看它继承树,这里给出一些实现或继承该接口的关键类或接口。

LifecycleListener

LifecycleListener表示对某一个生命周期事件的监听。这个接口非常简单,只有一个方法。

 //定义某一事件发生时需要的行为
public void lifecycleEvent(LifecycleEvent event);

LifecycleEvent

LifecycleEvent继承自Java的事件对象EventObject,是一个简单的类,由事件相关组件、事件的类型和事件相关数据组成。

public final class LifecycleEvent extends EventObject {
private static final long serialVersionUID = 1L;
private final Object data;
private final String type; public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.type = type;
this.data = data;
} public Object getData() {
return (this.data);
} public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
} public String getType() {
return (this.type);
}
}

LifecycleException

LifecycleException表示一个生命周期相关的异常,继承自Java的Exception类,提供了多种不同的构造函数,此外不能自定义它的子类。

public final class LifecycleException extends Exception {
private static final long serialVersionUID = 1L; public LifecycleException() {
super();
} public LifecycleException(String message) {
super(message);
} public LifecycleException(Throwable throwable) {
super(throwable);
} public LifecycleException(String message, Throwable throwable) {
super(message, throwable);
}
}

LifecycleState

LifecycleState枚举出了一个组件合法的生命周期状态,并对外提供两个参数,一个是获取生命周期事件,即在该状态下应该调用哪类生命周期事件,另一个是在该状态下能否调用组件除了getter/setter和生命周期方法外的其他public方法。

public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null),
MUST_STOP(true, null),
MUST_DESTROY(false, null); private final boolean available;
private final String lifecycleEvent; private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
} //能否调用其他公共分方法
public boolean isAvailable() {
return available;
} public String getLifecycleEvent() {
return lifecycleEvent;
}
}

你会发现在枚举中有很多之前没有提到的状态,下面列出各个状态之间的转换关系:

主要状态有:初始(初始状态,初始中,初始后),启动(启动前,启动中,启动后),停止(停止前,停止中,停止后),销毁(销毁前,销毁中,销毁后)

LifecycleSupport

LifecycleSupport是用来将事件通知给一个组件的所有监听器的辅助类。它包含了组件和该组件所有的监听器。其中监听器用了线程安全的CopyOnWriteArrayList来存储,主要的事件通知函数如下:

public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
for (LifecycleListener listener : listeners) {
listener.lifecycleEvent(event);
}
}

LifecycleBase

LifecycleBase是实现了Lifecycle的抽象类。它通过持有一个LifecycleSupport来管理监听器。具体的状态函数使用了模板方法模式,LifecycleBase规定了个状态之间的转换规则(是否合法以及状态间的自动转换等,具体参看LifecycleState中的状态转换图),而让用户继承的子类来实现具体的操作。由于代码较多,举一个start方法的例子。

public final synchronized void start() throws LifecycleException {

        if (LifecycleState.STARTING_PREP.equals(state) ||
LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) { if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted",
toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted",
toString()));
} return;
} if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)){
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
} setStateInternal(LifecycleState.STARTING_PREP, null, false); try {
//调用用户实现的方法
startInternal();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.startFail",toString()), t);
} if (state.equals(LifecycleState.FAILED) ||
state.equals(LifecycleState.MUST_STOP)) {
stop();
} else {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
} setStateInternal(LifecycleState.STARTED, null, false);
}
} //用户实现的抽象方法
protected abstract void startInternal() throws LifecycleException;

四、生命周期重要过程

1. 观察者注册 
观察者的注册可以通过xml方式配置,也可以通过直接调用Lifecycle的观察者添加方法。tomcat配置文件目录conf下面的server.xml中观察者配置如下:

  1. <Server port="8005" shutdown="SHUTDOWN">
  2. <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  3. <Listener className="org.apache.catalina.core.JasperListener" />
  4. <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  5. <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  6. ...
  7. </Server>

LifecycleSupport的观察者注册代码如下:

  1. public final class LifecycleSupport {
  2. // 观察者数组
  3. private LifecycleListener listeners[] = new LifecycleListener[0];
  4. ...
  5. public void addLifecycleListener(LifecycleListener listener) {
  6. synchronized (listenersLock) {
  7. LifecycleListener results[] =
  8. new LifecycleListener[listeners.length + 1];
  9. for (int i = 0; i < listeners.length; i++)
  10. results[i] = listeners[i];
  11. results[listeners.length] = listener;
  12. listeners = results;
  13. }
  14. }
  15. }

观察者是通过数组来维护,每次增加一个新的观察者,都需要将当前数组长度加1,将原来数组内容拷贝到新的数组中。对这里的设计我比较困惑,为什么采用这种数组扩容方式,这样每次增加新增观察者都需要数组拷贝,影响性能。可能的一个原因是,考虑到观察者数目少和新增的次数少,这种方式可以减少内存占用。

2. 通知观察者 
组件的生命周期中状态发生改变时,都会发出事件,通知观察者处理。下面以LifecycleBase中init()方法举例说明。

  1. public abstract class LifecycleBase implements Lifecycle {
  2. private LifecycleSupport lifecycle = new LifecycleSupport(this);
  3. // 当前状态
  4. private volatile LifecycleState state = LifecycleState.NEW;
  5. public synchronized final void init() throws LifecycleException {
  6. if (!state.equals(LifecycleState.NEW)) {
  7. invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
  8. }
  9. // 状态转移到INITIALIZING,会发送事件
  10. setState(LifecycleState.INITIALIZING);
  11. initInternal();
  12. setState(LifecycleState.INITIALIZED);
  13. }
  14. protected synchronized void setState(LifecycleState state, Object data) {
  15. ...
  16. this.state = state;
  17. // state为枚举类型,获取该枚举值对应的事件类型
  18. String lifecycleEvent = state.getLifecycleEvent();
  19. if (lifecycleEvent != null) {
  20. // 发起事件通知
  21. fireLifecycleEvent(lifecycleEvent, data);
  22. }
  23. }
  24. // 调用LifecycleSupport进行事件处理
  25. protected void fireLifecycleEvent(String type, Object data) {
  26. lifecycle.fireLifecycleEvent(type, data);
  27. }
  28. }

LifecycleSupport中的事件处理方法如下:

  1. public void fireLifecycleEvent(String type, Object data) {
  2. // 包装事件类型和数据
  3. LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
  4. // 循环,通知所有观察者进行事件处理
  5. LifecycleListener interested[] = listeners;
  6. for (int i = 0; i < interested.length; i++)
  7. interested[i].lifecycleEvent(event);
  8. }

3. 观察者事件处理 
以ServerLifecycleListener为例,说明观察者事件处理过程。 
public class ServerLifecycleListener 
    implements ContainerListener, LifecycleListener, PropertyChangeListener { 
    ... 
    public void lifecycleEvent(LifecycleEvent event) { 
        Lifecycle lifecycle = event.getLifecycle(); 
        if (Lifecycle.START_EVENT.equals(event.getType())) { 
                if (lifecycle instanceof Server) { 
                    ... 
                } 
                if( lifecycle instanceof Service ) { 
                   ... 
                }           
                if (lifecycle instanceof StandardContext){ 
                    ... 
                } 
            
        } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) { 
                ... 
        } 
    } 

观察者可以通过事件来源(lifecycle)和事件类型(eventType)对事件分类处理。

四、 总结 
tomcat中事件处理机制比较灵活,在日常工作的设计中值得借鉴,比如下面的业务场景:对客户投诉的创建、撤销、终止等,可以采用如下处理方式: 
--生命周期管理-- 
1. 创建统一的投诉业务生命周期Lifecycle,如create、cancel、destroy等。 
2. 定义投诉业务的状态枚举类(对应tomcat中LifecycleState),枚举类中定义每个状态对应的事件类型。 
--观察者注册-- 
3. 创建观察者管理service(对应tomcat中的LifecycleSupport)。观察者列表可以通过spring bean方式注入。 
--观察者通知-- 
4. 在生命周期中状态改变时,比如投诉创建时,发送事件通知,调用观察者管理service,通知观察者处理。 
5. 包装观察者所需要的数据(对应tomcat中的LifecycleEvent),如事件来源、类型等,供观察者使用。 
--观察者处理-- 
6. 定义实际观察者,按事件来源和类型分别做业务处理,比如投诉创建时,将投诉发生时用户的业务开通快照记录下来。

本文转自:https://blog.csdn.net/u013291394/article/details/50180753  http://learnworld.iteye.com/blog/1013751

最新文章

  1. axis2开发webservice入门到精通
  2. Cookie——Javascript
  3. ORACLE数据库的限制
  4. Week1 学长的经验教训
  5. ElasticSearch中文分词(IK)
  6. 安装tomcat出现failed to install tomcat8 service错误及解决方法
  7. 【css面试题】三个DIV要求水平对齐,左右两个DIV宽度固定为100px,中间那个DIV充满剩余的宽度(至少2种方法)
  8. IE6下a标签失效(背景穿透)
  9. RedHat7上安装MySQL5.7.16
  10. Linux 学习记录 五(软件的安装升级).
  11. linux下统计某个进程的CPU占用和内存使用
  12. 【20170521校内模拟赛】热爱生活的小Z
  13. 运行ant脚本(转载)
  14. html常用标签的取值和赋值操作
  15. CPU漏洞补丁KB4056892 卸载及忽略办法
  16. Xshell 无法连接虚拟机中的ubuntu的问题
  17. WPF Application 类介绍以及怎样修改启动方式
  18. 关于Java开发一职的经验
  19. JSPatch实现原理详解
  20. docker私服registry管理镜像

热门文章

  1. python之模块csv之CSV文件的写入(按行写入)
  2. servlet 服务器HTTP响应头设置示例(response用法)
  3. JProfiler 解决 Java 服务器的性能跟踪
  4. openGL 坐标系的互相转换
  5. web.xml文件头出错
  6. django和mysql
  7. JavaScript 设计模式之代理模式
  8. 让你的APP和你的服务器畅快通讯
  9. Linux命令-下载文件的工具:wget
  10. OAF_OAF增删改-新增的实现(案例)