最近在阅读“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接口的默认实现,实现init、start、stop、destroy等方法。对观察者的增加、查找和删除等操作会适配器方式,由组合的LifecycleSupport实例来完成。

4)LifecycleSupport

观察者的实际管理类,实现观察者的注册、删除、查询、调用等操作。

5)LifecycleListener

生命周期的观察者,定义了观察者的事件处理接口lifecycleEvent(LifecycleEvent event)。

6)ServerLifecycleListener

实际的观察者,实现了事件处理接口。

7)LifecycleEvent

观察者使用的参数,它封装了事件来源、事件类型和事件数据,使得观察者可以按事件来源和事件类型分类处理事件。

三、生命周期重要过程

1. 观察者注册

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

<Server port="8005" shutdown="SHUTDOWN">  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />  <Listener className="org.apache.catalina.core.JasperListener" />  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
...
</Server>  

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

public final class LifecycleSupport {  // 观察者数组  private LifecycleListener listeners[] = new LifecycleListener[0];  ...  public void addLifecycleListener(LifecycleListener listener) {  synchronized (listenersLock) {  LifecycleListener results[] =  new LifecycleListener[listeners.length + 1];  for (int i = 0; i < listeners.length; i++)  results[i] = listeners[i];  results[listeners.length] = listener;  listeners = results;  }  }
}  

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

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

public abstract class LifecycleBase implements Lifecycle {  private LifecycleSupport lifecycle = new LifecycleSupport(this);  // 当前状态  private volatile LifecycleState state = LifecycleState.NEW;  public synchronized final void init() throws LifecycleException {  if (!state.equals(LifecycleState.NEW)) {  invalidTransition(Lifecycle.BEFORE_INIT_EVENT);  }  // 状态转移到INITIALIZING,会发送事件  setState(LifecycleState.INITIALIZING);  initInternal();  setState(LifecycleState.INITIALIZED);  }  protected synchronized void setState(LifecycleState state, Object data) {  ...  this.state = state;  // state为枚举类型,获取该枚举值对应的事件类型  String lifecycleEvent = state.getLifecycleEvent();  if (lifecycleEvent != null) {  // 发起事件通知  fireLifecycleEvent(lifecycleEvent, data);  }  }  // 调用LifecycleSupport进行事件处理  protected void fireLifecycleEvent(String type, Object data) {  lifecycle.fireLifecycleEvent(type, data);  }
}  

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

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

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. 定义实际观察者,按事件来源和类型分别做业务处理,比如投诉创建时,将投诉发生时用户的业务开通快照记录下来。

转载至:http://learnworld.iteye.com/blog/1013751

tomcat事件处理机制相关推荐

  1. java事件处理模型_从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  2. ​iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景.

    2019独角兽企业重金招聘Python工程师标准>>> 主要是记录下iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景. 一.处理机制 界面响应消息机制分两块,(1)首先在 ...

  3. Android平台的事件处理机制和手指滑动例子

    Android平台的事件处理机制有两种 基于回调机制的事件处理:Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件. 基于 ...

  4. Android中的事件处理机制

    Android提供了强大的事件处理机制,它包括两套处理机制: 1.基于监听的事件处理 2.基于回调的事件处理 对于Android基于监听的事件处理,主要的做法是为Android界面组件绑定特定的事件监 ...

  5. QT开发(十二)——QT事件处理机制

    一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...

  6. Android基于监听的事件处理机制

    Android提供了强大的事件处理机制,主要包括两大类: 1,基于监听的事件处理机制:主要做法是为Android界面组件绑定特定的事件监听器 2,基于回调的事件处理机制:主要做法是重写Android组 ...

  7. 图解Tomcat类加载机制(阿里面试题)

    Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给 ...

  8. Cocos2d-JS事件处理机制

    在很多图形用户技术中,事件处理机制一般都有三个重要的角色:事件.事件源和事件处理者.事件源是事件发生的场所,通常就是各个视图或控件,事件处理者是接收事件并对其进行处理的一段程序. 事件处理机制中三个角 ...

  9. Qt 事件处理机制-qt源码解读

    在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent. 接下来依次谈谈Qt中有谁来产生.分发.接受和处理事件. 本篇来介绍Qt 事件处理机制.深入了解事件处理系统对于每个学习Qt人来 ...

最新文章

  1. 使用 ChatterBot 库制作一个聊天机器人
  2. Docker笔记:常用服务安装——Nginx、MySql、Redis(转载)
  3. .NET Framework3.0答疑
  4. spring 锁_分布式锁-快速实战
  5. Nmap 源代码学习四 软件简单使用
  6. 友元关系可以继承_C++知识点 30:友元
  7. unity package 包下载不下来
  8. 光纤跳线接口_一篇文章读懂光纤接头、尾纤、耦合器、终端盒的作用与接法!...
  9. 基于表面肌电信号的连续运动估计之前言(一)
  10. 一家旅游互联网公司技术的发展史
  11. 所谓的“互联网寒冬”,真的来了吗?
  12. Ubuntu wine 安装qq,微信
  13. RISC-V为中国MCU企业打开一个新窗口!
  14. lamp mysql开机自启_CentOS 程序开机自启动方法总结
  15. c++ STL 容器
  16. AXURE原型设计:数据可视化设计
  17. byte数组转blob类型_Jfinal 存byte[] 到mysql数据库中blob类型
  18. 锤子手机获工信部入网许可:清晰照曝光
  19. 五一出行哪种蓝牙耳机最好用?蓝牙耳机良心推荐
  20. 2.3 业务实现(微信获取用户信息详解)

热门文章

  1. php扩展模块作用及中文注释
  2. ssh框架从页面传中文发生乱码时怎么解决,就是添加一个字符编码拦截器。用springframework自带的便可...
  3. 如何执行静默(无人参与)Java 安装?
  4. IT餐馆—第三回 模式
  5. 2种造成sqlserver自增列不连续的原因
  6. 计算机网络TCP与UDP的区别
  7. 《剑指Offer》题目:合并两个排序的链表
  8. docker镜像-运行
  9. 在网页中显示CHM (c# csharp .net asp.net winform)
  10. 【结构型】Bridge模式