生命周期事件

  Catalina包含有很多组件。当Catalina启动时,这些组件也会启动,同样,当Catalina关闭时,这些组件也随之关闭,通过实现org.apache.catalina.Lifecycle接口,可以达到统一启动/关闭这些组件的效果。

实现Lifecycle接口的组件可以触发一个或多个下面的事件:BEFORE_START_EVENT、START_EVENT、AFTER_START_EVENT、BEFORE_STOP_EVENT、STOP_EVENT、AFTER_STOP_EVENT 。当组件启动时,正常会触发前3个事件,而关闭组件时,会触发后3个事件。如果Catalina组件可以触发事件,那么需要编写相应的事件监听器对这些事件进行响应。事件监听器是org.apache.catalina.LifecycleListener接口实例。

tomcat内部架构各个核心组件的包含关系。例如server包含service,service包含container,一层层包含。而这种结构类似数据结构中的树形结构,对于tomcat的启动也是鉴于此,可以通过父容器启动子容器,这样可以达到只要启动根容器,从而启动所有的组件,同时便于管理达到统一启动、停止、关闭的效果。

生命周期采用是观察者模式(监听事件)。

                                                     

简单看一下tomcat的设计源码

事件对象LifecycleEvent

public final class LifecycleEvent extends EventObject {

    private static final long serialVersionUID = 1L;

    // ----------------------------------------------------------- Constructors

    /**
* 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;
} // ----------------------------------------------------- Instance Variables /**
* The event data associated with this event.
*/
private Object data = null; /**
* The event type this instance represents.
*/
private String type = null; // ------------------------------------------------------------- Properties /**
* Return the event data of this event.
*/
public Object getData() { return (this.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); } }

事件监听接口LifecycleListener

public interface LifecycleListener {

    /**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event); }

事件监听实现类JasperListener

public void lifecycleEvent(LifecycleEvent event) {

        if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
try {
// Set JSP factory
Class.forName("org.apache.jasper.compiler.JspRuntimeContext",
true,
this.getClass().getClassLoader());
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// Should not occur, obviously
log.warn("Couldn't initialize Jasper", t);
}
// Another possibility is to do directly:
// JspFactory.setDefaultFactory(new JspFactoryImpl());
} }

事件监听类LifecycleSupport

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;
} }
//触发事件
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); }
//移除事件
public void removeLifecycleListener(LifecycleListener listener) { synchronized (listenersLock) {
int n = -1;
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] == listener) {
n = i;
break;
}
}
if (n < 0)
return;
LifecycleListener results[] =
new LifecycleListener[listeners.length - 1];
int j = 0;
for (int i = 0; i < listeners.length; i++) {
if (i != n)
results[j++] = listeners[i];
}
listeners = results;
} }

事件源 ServerStandard@startInternal()

//触发事件
protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services
synchronized (services) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}

下面写了一个简单观察者模式的例子,便于理解。

import java.util.ArrayList;
import java.util.List; class MacBookPro{ public List<ITClient> clients = new ArrayList<ITClient>(); public void addClientListener(ITClient client){
clients.add(client);
}
public void notifyClient(String info){
//通知所有放入监听者
clients.forEach(x->x.receiveInfo(info));
}
}
class ITClient{ private String name; public ITClient(String name)
{
this.name = name;
}
public void receiveInfo(String info){
System.out.println(this.name+" :: "+info);
}
}
public class StateTest
{
public static void main(String[] args)
{
MacBookPro mbp = new MacBookPro();
ITClient c1 = new ITClient("员工1");
ITClient c2 = new ITClient("员工2");
ITClient c3 = new ITClient("员工3");
mbp.addClientListener(c1);
mbp.addClientListener(c2);
mbp.addClientListener(c3);
System.out.println("促销活动开始了");
mbp.notifyClient("京东618大减价");
}
}

结果:

促销活动开始了
员工1 :: 京东618大减价
员工2 :: 京东618大减价
员工3 :: 京东618大减价

Tomcat学习笔记(五)的更多相关文章

  1. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  2. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  3. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  4. Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  5. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. ES6学习笔记<五> Module的操作——import、export、as

    import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...

  7. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  8. python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍

    python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...

  9. Go语言学习笔记五: 条件语句

    Go语言学习笔记五: 条件语句 if语句 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 竟然没有括号,和python很像.但是有大括号,与python又不一样. 例子: pa ...

随机推荐

  1. java高并发之CountDownLatch,CyclicBarrier和join

    晚上打车回家,在车上看到一篇文章<22岁大学生获谷歌天价Offer,年薪千万!>,讲的是印度一个22岁大学生多次参加ACM大赛,开源多个项目,以非常牛逼的履历通过了谷歌的AI测试,斩获谷歌 ...

  2. JS - 给String.prototype添加replaceAll方法

    String.prototype.replaceAll = function (targetStr, newStr) {  var sourceStr = this.valueOf();  while ...

  3. Java OOP——第七章 多线程

    1.进程:是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间): Eg:用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间.当用户再次点击左面的IE浏览器, ...

  4. oracle中序列,同义词的创建

    序列 序列是用来生成唯一,连续的整数的数据库对象.序列通常用来自动生成主机那或唯一键的值.序列可以按升序排序, 也可以按降序排序.例如,销售流水表中的流水号可以使用序列自动生成. 创建序列语法: cr ...

  5. css3 媒体查询的学习。

    1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...

  6. 初试PHP连接sql server

    最开始想使用 pdo_sqlsrv 拓展,但是一直没成功,本文采用的是 pdo_dblib + freetds. 环境:CentOS 6.8.PHP 5.6.20 freetds wget ftp:/ ...

  7. Alice’s Stamps HDU - 6249 (区间DP)

    点击传送 Alice’s Stamps Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  8. 04,Python网络爬虫之requests模块(1)

    引入 Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. 警告:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症.冗余代码症.重新发明轮子症.啃文档 ...

  9. Spring---BeanFactory与ApplicationContext简介

    BeanFactory概念 Spring通过一个配置文件描述bean和bean之间的依赖关系,然后利用java语言的反射功能实例化bean,并建立bean之间的依赖关系.Spring的IOC容器在完成 ...

  10. 《Cracking the Coding Interview》——第10章:可扩展性和存储空间限制——题目7

    2014-04-24 22:06 题目:搜索引擎问题,如果有一列100台服务器的集群,用来响应查询请求,你要如何设计query分发和cache策略? 解法:query分发可以用计算数字签名并对机器数取 ...