Tomcat的生命周期管理
来源:互联网 发布:原单 知乎 编辑:程序博客网 时间:2024/05/21 05:56
Servlet规范中定义了一个Servlet的生命周期, Tomcat使用事件方式管理Servlet的生命周期。 Tomcat定义了一个Lifecycle接口统一管理在容器内发生的所有事件。
Lifecycle接定义了两个方法start, stop来完成创建,初始化和结束的生命周期管理。
Lifecycle接口一共定义了九种事件类型。 所有容器内处理Servlet的类都继承该接口, 如StandarServer, StandarPipeline,ContainerBase以及各种Valve。
本文主要分析Tomcat中声明周期管理的设计和实现。
一,设计: Tomcat使用了组合(Composite)和观察者(Observer)模式。
设计核心是: Lifecycle, LifecycleListener, LifecycleEvent和LifecycleSupport
Lifecycle组合了LifecycleSupport,
1. 注册事件: Lifecycle中定义的addLifecycleListener实际是使用LifecycleSupport的addLifecycleListener。
2. 通知监听者: 当Lifecycle中发生动作尤其是start和stop时会调用LifecycleSupport的fireLifecycleEvent。 这个时候LifecycleSupport的fireLifecycleEvent会根据传入的事件类型,生成LifecycleEvent事件源并且遍历通知所有注册在里面的监听(LifecycleListener)的lifecycleEvent方法.
3. 监听者响应: 监听(LifecycleListener)会根据不同的事件类型做不同的操作。
二, 实现:
以JasperListener(初始化JSP编译引擎)监听在StandarServer的注册,通知和响应为例。
1. 注册事件: Tomcat允许用户自定义监听和加入,可以在serer.xml中灵活的配置。
<Server port="8005" shutdown="SHUTDOWN"> ... ... <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> <Listener className="org.apache.catalina.core.JasperListener" /> ... ...</Server>
StandardServer继承Lifecycle接口, 有注册监听的方法。
StandardServer中注册监听的代码片断:
org.apache.catalina.core.StandardServer
public final class StandardServer implements Lifecycle, Server, MBeanRegistration { ... ... // 组合模式 private LifecycleSupport lifecycle = new LifecycleSupport(this); ... ... // 将监听加入到模块中 public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } ... ...}
org.apache.catalina.util.LifecycleSupport 中addLifecycleListener方法完成注册监听的具体实现:
public final class LifecycleSupport { ... ... 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; } } ... ...}
Tomcat在启动的时候会将xml中配置的内容加载进去,(见《Tomcat中xml的解析器Digester》), 完成监听注册。
2. 通知监听者。
StandardServer在自身初始化的时候通知所有监听有初始化事件发生。
public void initialize() throws LifecycleException { if (initialized) { log.info(sm.getString("standardServer.initialize.initialized")); return; } lifecycle.fireLifecycleEvent(INIT_EVENT, null); initialized = true; ... ...}
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. 监听者响应
当LifecycleListener被调用lifecycleEvent方法, 会分析事件的类型, 根据类型做不同的响应或者不响应。
org.apache.catalina.core.JasperListener被注册在StandardServer,当StandardServer通知事件的时候, 它也会被调用。
调用到底方法是: lifecycleEvent
public class JasperListener implements LifecycleListener { ... ... public void lifecycleEvent(LifecycleEvent event) { // 判断事件类型, 根据类型作出响应 if (Lifecycle.INIT_EVENT.equals(event.getType())) { try { // Set JSP factory Class.forName("org.apache.jasper.compiler.JspRuntimeContext", true, this.getClass().getClassLoader()); } catch (Throwable t) { // Should not occur, obviously log.warn("Couldn't initialize Jasper", t); } // Another possibility is to do directly: // JspFactory.setDefaultFactory(new JspFactoryImpl()); } } ... ...}
至此, Tomcat的生命周期管理分析就完成了。 可以看出Tomcat的生命周期管理设计的非常灵活和简单, 用户可以自如的加入不同监听到各个环节。
但也看出这个设计也有一些缺点, 比如每个监听都会被通知一遍,然后自己去判断事件类型。 如果容器发生的事件多而且监听也多, 会造成很多不必要的损耗。当然Tomcat的这个问题不是很大, 因为Tomcat发生的事件不多而且监听也不是很多。
- Tomcat的生命周期管理
- Tomcat的生命周期管理
- Tomcat的生命周期管理简要分析
- Tomcat的生命周期管理简要分析
- Tomcat的生命周期管理简要分析
- Tomcat的生命周期管理简要分析
- tomcat生命周期的管理——生命周期统一接口Lifecycle
- Tomcat(2)生命周期管理
- TOMCAT源码分析-生命周期管理
- Tomcat源码分析--生命周期管理
- Tomcat生命周期的实现
- Tomcat 体系结构、关键组件及生命周期管理
- tomcat源码分析二:生命周期管理
- Tomcat生命周期管理与观察者模式
- TOMCAT源码分析-生命周期管理2
- 管理Activity的生命周期
- session的生命周期管理
- 管理Activity的生命周期
- 存储过程和触发器
- onvif 客户端
- Replication Factor实现数据备份
- mkimage制作linux内核映像[转载
- 新浪、qq的账号登录及PHP api操作
- Tomcat的生命周期管理
- C# Format详解
- TableRow中控制里面控件的大小
- (译)cocos2d菜单教程:第一部分
- Java中 volatile 关键字
- Go语言中对图像进行缩放
- 分区表学习总结
- 关于android.view.InflateException: Binary XML file line #7: Error inflating class ViewPager错误的原因及解决办法
- (译)cocos2d菜单教程:第二部分