how tomcat works 六 生命周期
我觉得这一章叫tomcat中的观察者模式,比较好!
首先,不要看本章,请查看一下关于观察者模式的资料比较好。
推荐以下知识点
基础篇
设计模式之禅----观察者模式
大家可以找到pdf阅读一下
另外本人的博客中也有一篇<<谈谈观察者模式 >> 很久之前写的,是阅读上书观察者模式时做的笔记,写的实在不敢恭维,如果找不到书,倒是可以看看鄙人的博客。
http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html
上面的这个博客,让具体的观察者和被观察者耦合,大家可以看看。
进阶篇
http://blog.csdn.net/lovelion/article/details/7720232
看了上面的一个pdf两个博客,我就认为大家理解了观察者模式,现在咱们开始说tomcat;
第六章的题目叫做生命周期,说的内容就是如何在上级容器启动或者关闭的时候,可以自动启动或关闭它的组件。
其实更准确的说是,在上级容器启动的时候如何通知别的容器(因为要实现父容器启动,子组件也启动,很简单,循环获得所有子组件,调用start方法即可)
几个类和接口
Lifecycle接口
我们既然说到生命周期,说到事件,那总得有个接口来表示这些事件吧
package org.apache.catalina; public interface Lifecycle { 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 void addLifecycleListener(LifecycleListener listener); public LifecycleListener[] findLifecycleListeners(); public void removeLifecycleListener(LifecycleListener listener); public void start() throws LifecycleException; public void stop() throws LifecycleException; }
一共六个事件类型开始,结束等等。下面的几个方法见名知意不再赘述。
LifeEvent类
package org.apache.catalina; import java.util.EventObject; public final class LifecycleEvent extends EventObject { private Object data = null; private Lifecycle lifecycle = null; private String type = null; public LifecycleEvent(Lifecycle lifecycle, String type) { this(lifecycle, type, null); } public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super(lifecycle); this.lifecycle = lifecycle; this.type = type; this.data = data; } public Object getData() { return (this.data); } public Lifecycle getLifecycle() { return (this.lifecycle); } public String getType() { return (this.type); }<pre name="code" class="java">
}
这个Event很简单,就是哪个实现了Lifecycle接口的对象在某个时间发生了某件事。
LifecycleListener接口
<pre name="code" class="java">package org.apache.catalina; import java.util.EventObject; public interface LifecycleListener { public void lifecycleEvent(LifecycleEvent event); }
这就相当于上面几篇博客中的Observiser接口,lifecycleEvent就是update方法,不同的是前面几篇博客中,实现LifecycleListener接口的对象就是监听的实体,这里不是*************
LifecycleSupport类
一个对象,可以给自己增加多个监听器,这个多个监听器可以组成一个数组或其他类似的结构中,这个功能就由LifecycleSupport类来实现。
package org.apache.catalina.util; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; public final class LifecycleSupport { public LifecycleSupport(Lifecycle lifecycle) { super(); this.lifecycle = lifecycle; } private Lifecycle lifecycle = null; private LifecycleListener listeners[] = new LifecycleListener[0]; public void addLifecycleListener(LifecycleListener listener) { synchronized (listeners) { 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 LifecycleListener[] findLifecycleListeners() { return listeners; } public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = null; synchronized (listeners) { interested = (LifecycleListener[]) listeners.clone(); } for (int i = 0; i < interested.length; i++) interested[i].lifecycleEvent(event); } public void removeLifecycleListener(LifecycleListener listener) { ..省略代码 } }
我们看看那个fireLifecycleEvent(String type, Object data),它就是上面几篇博客中Subjet中的notify方法,依次调用每个listener的lifeEvent()方法(就是上面说的update方法)。
ok,我们看应用程序
应用程序
xml图如下:
看看SimpleContext与LifecycleSuppot,它们是使用的关系,SimpleContext中有一个LifecycleSuppot,
代码如下
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
其实每一个实现了Lifecycle接口的组件,都可以有一个LifecycleSupport。
另外,还有一个布尔型变量started,来知识容器是否已经启动。
现在我们看看SimpleContext中实现Lifecycle接口中的方法。
public synchronized void start() throws LifecycleException { if (started) throw new LifecycleException("SimpleContext has already started"); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); started = true; try { // Start our subordinate components, if any if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); // Start our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } // Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null); } catch (Exception e) { e.printStackTrace(); }
本节的启动程序与上一节没有什么区别,除了
LifecycleListener listener = new SimpleContextLifecycleListener(); ((Lifecycle) context).addLifecycleListener(listener);
context的addLifecycleListener方法,就是把监听器(就是上面说的李斯)放到context中的LifecycleSuppour的数组中去!
我们再看看SimpleContextLifecycleListener
public class SimpleContextLifecycleListener implements LifecycleListener { @SuppressWarnings("unused") public void lifecycleEvent(LifecycleEvent event) { Lifecycle lifecycle = event.getLifecycle(); System.out.println("SimpleContextLifecycleListener's event " +event.getType().toString()); if (Lifecycle.START_EVENT.equals(event.getType())) { System.out.println("Starting context."); } else if (Lifecycle.STOP_EVENT.equals(event.getType())) { System.out.println("Stopping context."); } } }
不用解释了吧。
其实在本节程序里,我们只是给SimpleContext加了一个监听器,换句话说,SimpleWrapper中的start方法中虽然也有lifecycle.fireLifecycleEvent(START_EVENT, null)方法,但是LifecycelSupport中的数组中并没有监听器,也就没有什么通知的了。
最后我们运行起来看看
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
SimpleContextLifecycleListener's event before_start
Starting SimpleLoader
Starting Wrapper Modern
Starting Wrapper Primitive
SimpleContextLifecycleListener's event start
Starting context.
SimpleContextLifecycleListener's event after_start
Wrapper,Loader的start方法只是在屏幕中打印出信息,并没有再次触发什么事件。
一点感觉
总感觉这一章怪怪的,要说是启动子容器,直接循环取得子容器,然后调用start方法即可;观察者模式在本节的作用就是打印出
SimpleContextLifecycleListener's event before_start
SimpleContextLifecycleListener's event start
SimpleContextLifecycleListener's event after_start
这三句话而已,似乎没有什么大的作用。
后来我仔细想想观察者模式,它就是一个通知的作用,通知所有关注自己的对象,只有那观察者知道自己观察的对象有了状态变化之后干什么,就不是观察者模式考虑的是事了,观察者模式只管通知!
在本节,观察者只是打印出一句话,所以显得比较简单而已,当然要想复杂改LifecycleListener类的lifecycleEvent方法即可。
how tomcat works 六 生命周期的更多相关文章
- Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
Tomcat 8(七)解读Bootstrap介绍过.运行startup.bat.将引发Tomcat一连串组件的启动.事实上这一连串启动是通过组件的生命周期(Lifecycle)实现的 今天来看看Lif ...
- LitElement(六)生命周期
1.概述 基于LitElement的组件通过响应观察到的属性更改而异步更新. 属性更改是分批进行的,如果在请求更新后,更新开始之前,发生更多属性更改,则所有更改都将捕获在同一次更新中. 在较高级别上, ...
- How Tomcat works — 六、tomcat处理请求
tomcat已经启动完成了,那么是怎么处理请求的呢?怎么到了我们所写的servlet的呢? 目录 Http11ConnectionHandler Http11Processor CoyoteAdapt ...
- How tomcat works(深入剖析tomcat)生命周期Lifecycle
How Tomcat Works (6)生命周期Lifecycle 总体概述 这一章讲的是tomcat的组件之一,LifeCycle组件,通过这个组件可以统一管理其他组件,可以达到统一启动/关闭组件的 ...
- 【微信小程序开发•系列文章六】生命周期和路由
这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...
- 【转】Tomcat组件生命周期管理
Tomcat组件生命周期管理 Tomcat中Server,Service,Connector,Engine,Host,Context,它们都实现了org.apache.catalina.Lifecyc ...
- Servlet第六篇【Session介绍、API、生命周期、应用】
什么是Session Session 是另一种记录浏览器状态的机制.不同的是Cookie保存在浏览器中,Session保存在服务器中.用户使用浏览器访问服务器的时候,服务器把用户的信息以某种的形式记录 ...
- Tomcat 源码分析(一)——启动与生命周期组件
写在前面的话:读Tomcat源码也有段时间了,大领悟谈不上.一些小心得记录下来,供大家参考相护学习. 一.启动流程 Tomcat启动首先需要熟悉的是它的启动流程.和初学者第一天开始写Hello Wor ...
- Servlet第六篇【Session介绍、API、生命周期、应用、与Cookie区别】
什么是Session Session 是另一种记录浏览器状态的机制.不同的是Cookie保存在浏览器中,Session保存在服务器中.用户使用浏览器访问服务器的时候,服务器把用户的信息以某种的形式记录 ...
随机推荐
- 初识Spring Boot框架
前面的铺垫文章已经连着写了六篇了,主要是介绍了Spring和SpringMVC框架,小伙伴们在学习的过程中大概也发现了这两个框架需要我们手动配置的地方非常多,不过做JavaEE开发的小伙伴们肯定也听说 ...
- [Mysql]Innodb 独立表空间和共享表空间
innodb有2中表空间方式: 共享表空间 和 独立表空间 查询数据的设置: show variables like '%per_table'; 默认是共享表空间,独立表空间在配置文件中添加 inno ...
- 如何在苹果手机上安装自制的AD证书
写这篇博文的契机是有人已经实现了CRM在用自制证书部署IFD后,在手机安装上自制证书后即可登录官方移动端APP,因为之前很多人都尝试过只要是自制证书部署的IFD就无法使用官网手机APP,而本人实验下来 ...
- ubuntu mysql表名大小写区分
近期开发线上操作系统用的ubuntu,数据库用的mysql,突然发现mysql表名大写报错,找一下原因,看了下mysql的配置,果真可以设置,窃喜. 先找到你MySQL的my.cnf配置文件并修改,当 ...
- 自定义圆角透明的Dialog
自定义圆角透明的Dialog 说明 系统默认的Dialog默认是背景不透明的,有时候项目需要Dialog为圆角透明,这个时候的解决方案就是---重写Dialog - 系统样式 - 自定义以后的样式 自 ...
- MonoBehaviour介绍(Unity3D开发之一)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=486 猴子自学Unity已经一段 ...
- Cytoscape源码下载地址和编译办法
开发环境:Windows2008 R2 64位+Jdk1.7+Maven3.2.3 前提条件:安装好JDK1.7到C:\Program Files\Java\jdk1.7.0_67,下载好Maven并 ...
- Oracle EBS R12文件系统结构(学习汇总网上资料)
Oracle EBS R12在服务器端文件结构如下: 顶层目录下面分为 1)inst --–跟ebs整个实例(instance)相关的配置信息以及其他信息 2) db ---主要存储DB层的信息 ...
- Zeroc Ice Slice语言使用 HelloWorld
Slice介绍 为了开发多语言支持的RPC服务,需要一种中立的新语言来定义这个服务接口,以便各个编程语言能够准确无误地理解和翻译接口,为此Ice设计了Slice语言.Ice开发的第一步 ...
- 《java入门第一季》之有趣的集合小案例---获取10个【1-20之间】的随机数,要求不能重复。
import java.util.ArrayList; import java.util.Random; /* * 获取10个[1-20之间]的随机数,要求不能重复.(注意:不是获取10个数,如果单纯 ...