设为首页 收藏本站
查看: 363|回复: 0

[经验分享] tomcat生命周期管理 LifeCycle

[复制链接]

尚未签到

发表于 2017-1-21 09:41:33 | 显示全部楼层 |阅读模式
  Servlet规范中定义了一个Servlet的生命周期, Tomcat使用事件方式管理Servlet的生命周期。 Tomcat定义了一个Lifecycle接口统一管理在容器内发生的所有事件。
DSC0000.gif

Lifecycle接定义了两个方法start, stop来完成创建,初始化和结束的生命周期管理。

Lifecycle接口一共定义了九种事件类型。 所有容器内处理Servlet的类都继承该接口, 如StandarServer, StandarPipeline,ContainerBase以及各种Valve。

本文主要分析Tomcat中声明周期管理的设计和实现。

Author: Benewu(at)gmail.com

一,设计: 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中灵活的配置。

Java代码





  • <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>  



<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


Java代码





  • public final class StandardServer   

  •     implements Lifecycle, Server, MBeanRegistration    
  •  {   
  •   
  •   ... ...   
  •   

  •     // 组合模式   

  •     private LifecycleSupport lifecycle = new LifecycleSupport(this);   
  •   
  •   ... ...   
  •   

  •     // 将监听加入到模块中   

  •     public void addLifecycleListener(LifecycleListener listener) {   
  •   
  •         lifecycle.addLifecycleListener(listener);   
  •   
  •     }   
  •   ... ...   
  •   
  • }  



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方法完成注册监听的具体实现:

Java代码





  • 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 = listeners;   
  •           results[listeners.length] = listener;   
  •           listeners = results;   
  •       }   
  •   
  •     }   
  •   ... ...   
  • }  



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 = listeners;
results[listeners.length] = listener;
listeners = results;
}
}
... ...
}

  

Tomcat在启动的时候会将xml中配置的内容加载进去,(见《Tomcat中xml的解析器Digester》), 完成监听注册。


2. 通知监听者。

StandardServer在自身初始化的时候通知所有监听有初始化事件发生。

Java代码





  •    public void initialize()   

  •         throws LifecycleException    
  •     {   

  •         if (initialized) {   

  •                 log.info(sm.getString("standardServer.initialize.initialized"));   

  •             return;   
  •         }   

  •         lifecycle.fireLifecycleEvent(INIT_EVENT, null);   

  •         initialized = true;   
  •   ... ...   
  • }  



   public void initialize()
throws LifecycleException
{
if (initialized) {
log.info(sm.getString("standardServer.initialize.initialized"));
return;
}
lifecycle.fireLifecycleEvent(INIT_EVENT, null);
initialized = true;
... ...
}

  

LifecycleSupport实现具体动作, 生成事件源并通知所有监听

Java代码





  • 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.lifecycleEvent(event);   
  •   
  • }  



    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.lifecycleEvent(event);
}

  

3. 监听者响应

当LifecycleListener被调用lifecycleEvent方法, 会分析事件的类型, 根据类型做不同的响应或者不响应。

org.apache.catalina.core.JasperListener被注册在StandardServer,当StandardServer通知事件的时候, 它也会被调用。
调用到底方法是: lifecycleEvent

Java代码





  • 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());   
  •         }   
  •   
  •     }   
  •   
  •    ... ...   
  • }  



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发生的事件不多而且监听也不是很多。


参考:
1 Java Servlet概述
http://tech.ccidnet.com/art/1077/20041123/180515_1.html

Java代码





  •   




  

2 Tomcat 6官方文档
http://tomcat.apache.org/tomcat-6.0-doc/index.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-331429-1-1.html 上篇帖子: TOMCAT配置相关(转) 下篇帖子: Tomcat内存配置及优化
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表