tomcat生命周期

本文转自:http://www.iteye.com/topic/694644

在之前的 Tomcat 整体架构中可以看到 Tomcat 包含多个很多个组件 , 今天我们来看看, Tomcat 是如何管理这些组件的生命周期的。
我们知道,组件与组件之间,必须建立起相互的关系,才能做到同时启动与停止。 Tomcat 内部,使用一个观察者模式来组织这些组件之间的关系。
我们来看看, Tomcat 启动时,它会做哪些处理……
日志:

Html代码   收藏代码
  1. ……  
  2.   
  3. 2010-6-19 15:41:18 org.apache.catalina.core.StandardService start  
  4. 信息 : Starting service Catalina  
  5. 2010-6-19 15:41:18 org.apache.catalina.core.StandardEngine start  
  6. 信息 : Starting Servlet Engine: Apache Tomcat/6.0.18  
  7. …  
  8. 2010-6-19 15:41:19 org.apache.coyote.http11.Http11Protocol start  
  9. 信息 : Starting Coyote HTTP/1.1 on http-8080  
  10. 2010-6-19 15:41:19 org.apache.jk.common.ChannelSocket init  
  11. 信息 : JK: ajp13 listening on /0.0.0.0:8009  
  12. 2010-6-19 15:41:19 org.apache.jk.server.JkMain start  
  13. 信息 : Jk running ID=0 time=0/182 config=null  
  14. 2010-6-19 15:41:19 org.apache.catalina.startup.Catalina start  
  15. 信息 : Server startup in 1706 ms  
 



我们看到,它的启动顺序:

Java代码   收藏代码
  1. StandardService --> StandardEngine-->Http11Protocol-->JkMain-->Catalina  
 


OK, 我们来看看在 Tomcat 内部的,他是如何做的
首先, Tomcat内部的生命周期的相关定义都在接口 Lifecycle 中,

 

Java代码   收藏代码
  1. package org.apache.catalina;  
  2.   
  3.   
  4. public interface Lifecycle {  
  5.   
  6.     public static final String INIT_EVENT = "init";  
  7.   
  8.     public static final String START_EVENT = "start";  
  9.   
  10.     public static final String BEFORE_START_EVENT = "before_start";  
  11.   
  12.     public static final String AFTER_START_EVENT = "after_start";  
  13.     public static final String STOP_EVENT = "stop";  
  14.     public static final String BEFORE_STOP_EVENT = "before_stop";  
  15.     public static final String AFTER_STOP_EVENT = "after_stop";  
  16.     public static final String DESTROY_EVENT = "destroy";  
  17.     public static final String PERIODIC_EVENT = "periodic";  
  18.     public void addLifecycleListener(LifecycleListener listener);  
  19.     public LifecycleListener[] findLifecycleListeners();  
  20.     public void removeLifecycleListener(LifecycleListener listener);  
  21.     public void start() throws LifecycleException;  
  22.     public void stop() throws LifecycleException;  
  23. }  

 

另外生命周期的相关事件,定义在 LifecycleEvent 类中

 

 

 

Java代码   收藏代码
  1. package org.apache.catalina;  
  2.   
  3.   
  4.   
  5. import java.util.EventObject;  
  6.   
  7.   
  8. public final class LifecycleEvent  
  9.   
  10.     extends EventObject {  
  11.     // ----------------------------------------------------------- Constructors  
  12.     public LifecycleEvent(Lifecycle lifecycle, String type) {  
  13.         this(lifecycle, type, null);  
  14.     }  
  15.   
  16.     public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {  
  17.         super(lifecycle);  
  18.         this.lifecycle = lifecycle;  
  19.         this.type = type;  
  20.         this.data = data;  
  21.     }  
  22.   
  23.     private Object data = null;  
  24.   
  25.     private Lifecycle lifecycle = null;  
  26.   
  27.     private String type = null;  
  28.   
  29.     public Object getData() {  
  30.         return (this.data);  
  31.     }  
  32.   
  33.     public Lifecycle getLifecycle() {  
  34.         return (this.lifecycle);  
  35.     }  
  36.   
  37.     public String getType() {  
  38.         return (this.type);  
  39.     }  
  40.   
  41. }  

 

 

关于事件的监听,在接口LifecycleListener 中有定义

 

 

Java代码   收藏代码
  1. package org.apache.catalina;  
  2.   
  3. public interface LifecycleListener {  
  4.     public void lifecycleEvent(LifecycleEvent event);  
  5. }  

 

 另外,这里还需要介绍一个特别的类:LifecycleSupport, 用于触发生命周期的相关事件.

 

Java代码   收藏代码
  1. package org.apache.catalina.util;  
  2.   
  3. import org.apache.catalina.Lifecycle;  
  4. import org.apache.catalina.LifecycleEvent;  
  5. import org.apache.catalina.LifecycleListener;  
  6.   
  7. public final class LifecycleSupport {  
  8.     public LifecycleSupport(Lifecycle lifecycle) {  
  9.         super();  
  10.         this.lifecycle = lifecycle;  
  11.     }  
  12.   
  13.     private Lifecycle lifecycle = null;  
  14.     private LifecycleListener listeners[] = new LifecycleListener[0];  
  15.     private final Object listenersLock = new Object(); // Lock object for changes to listeners  
  16.     public void addLifecycleListener(LifecycleListener listener) {  
  17.       synchronized (listenersLock) {  
  18.           LifecycleListener results[] =  
  19.             new LifecycleListener[listeners.length + 1];  
  20.           for (int i = 0; i < listeners.length; i++)  
  21.               results[i] = listeners[i];  
  22.           results[listeners.length] = listener;  
  23.           listeners = results;  
  24.       }  
  25.     }  
  26.   
  27.     public LifecycleListener[] findLifecycleListeners() {  
  28.         return listeners;  
  29.     }  
  30.   
  31.     public void fireLifecycleEvent(String type, Object data) {  
  32.         LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);  
  33.         LifecycleListener interested[] = listeners;  
  34.         for (int i = 0; i < interested.length; i++)  
  35.             interested[i].lifecycleEvent(event);  
  36.     }  
  37.   
  38.     public void removeLifecycleListener(LifecycleListener listener) {  
  39.         synchronized (listenersLock) {  
  40.             int n = -1;  
  41.             for (int i = 0; i < listeners.length; i++) {  
  42.                 if (listeners[i] == listener) {  
  43.                     n = i;  
  44.                     break;  
  45.                 }  
  46.             }  
  47.             if (n < 0)  
  48.                 return;  
  49.             LifecycleListener results[] =  
  50.               new LifecycleListener[listeners.length - 1];  
  51.   
  52.             int j = 0;  
  53.             for (int i = 0; i < listeners.length; i++) {  
  54.                 if (i != n)  
  55.                     results[j++] = listeners[i];  
  56.             }  
  57.             listeners = results;  
  58.         }  
  59.     }  
  60. }  

 

 

下面,我们来看看 StandardService 类的启动方法, 看它是如何启动的

   在service真正启动时,他首先会触发一些启动前的事件,
    然后启动它自己
    接着,它会启动它关联的容器对象,
    然后,将所有它的子组件—既连接器 全部都启动 ,下面是详细的代码/

Java代码   收藏代码
  1. public class StandardService  
  2.         implements Lifecycle, Service, MBeanRegistration   
  3.  {  
  4.    .............  
  5.     /** 
  6.      * The lifecycle event support for this component. 
  7.      */  
  8.     private LifecycleSupport lifecycle = new LifecycleSupport(this);  
  9.     .............  
  10.     /** 
  11.      * The set of Connectors associated with this Service. 
  12.        关联到这个Service的连接器对象. 
  13.      */  
  14.     protected Connector connectors[] = new Connector[0];  
  15.       
  16.     public void start() throws LifecycleException {  
  17.         // Validate and update our current component state  
  18.         if (log.isInfoEnabled() && started) {  
  19.             log.info(sm.getString("standardService.start.started"));  
  20.         }  
  21.           
  22.         if( ! initialized )  
  23.             init();   
  24.   
  25.         // 触发启动之前的事件  
  26.         lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);  
  27.         if(log.isInfoEnabled())  
  28.             log.info(sm.getString("standardService.start.name"this.name));  
  29.   
  30.         lifecycle.fireLifecycleEvent(START_EVENT, null);  <<<<(1)  
  31.         started = true;  
  32.         // Start our defined Container first 首先启动关联的容器  
  33.         if (container != null) {  
  34.             synchronized (container) {  
  35.                 if (container instanceof Lifecycle) {  
  36.                     ((Lifecycle) container).start();  
  37.                 }  
  38.             }  
  39.         }  
  40.   
  41.         synchronized (executors) {  
  42.             for ( int i=0; i<executors.size(); i++ ) {  
  43.                 executors.get(i).start();  
  44.             }  
  45.         }  
  46.   
  47.         // Start our defined Connectors second 再启动关联的连接器  
  48.         synchronized (connectors) {  
  49.             for (int i = 0; i < connectors.length; i++) {  
  50.                 if (connectors[i] instanceof Lifecycle)  
  51.                     ((Lifecycle) connectors[i]).start();  
  52.             }  
  53.         }  
  54.           
  55.         // Notify our interested LifecycleListeners  
  56.         lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);  
  57.   
  58.     }  

 

代码(1)处,显示出,在Service正式启动之前,它还会出发启动前的事件,我们来看看,这个方法具体做些什么.  调用LifecycleSupport 类的 fireLifecycleEvent(START_EVENT, null);方法

 

Java代码   收藏代码
  1. public void fireLifecycleEvent(String type, Object data) {  
  2.   
  3.         LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);  
  4.         LifecycleListener interested[] = listeners;  
  5.         for (int i = 0; i < interested.length; i++)  
  6.             interested[i].lifecycleEvent(event);  
  7.   
  8.     }  

 而在内部,Service启动时,这里真正调用的是类 ServerLifecycleListener的方法:

Java代码   收藏代码
  1. package org.apache.catalina.mbeans;  
  2.   
  3.   
  4.   
  5.   
  6.   
  7. public class ServerLifecycleListener  
  8.   
  9.     implements ContainerListener, LifecycleListener, PropertyChangeListener {  
  10.   
  11.   
  12.   
  13.     public void lifecycleEvent(LifecycleEvent event) {  
  14.   
  15.         Lifecycle lifecycle = event.getLifecycle();  
  16.         if (Lifecycle.START_EVENT.equals(event.getType())) {  
  17.   
  18.             if (lifecycle instanceof Server) {  
  19.                 createMBeans();  
  20.             }  
  21.   
  22.             // We are embedded.  
  23.             if( lifecycle instanceof Service ) {  
  24.                 try {  
  25.                     //Service启动时,触发的事件  
  26.                     MBeanFactory factory = new MBeanFactory();  
  27.                     createMBeans(factory);  
  28.                     createMBeans((Service)lifecycle);  
  29.                 } catch( Exception ex ) {  
  30.                     log.error("Create mbean factory");  
  31.                 }  
  32.             }  
  33.   
  34.             /* 
  35.             // Ignore events from StandardContext objects to avoid 
  36.             // reregistering the context 
  37.             if (lifecycle instanceof StandardContext) 
  38.                 return; 
  39.             createMBeans(); 
  40.             */  
  41.   
  42.         } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {  
  43.             try {  
  44.                 if (lifecycle instanceof Server) {  
  45.                     destroyMBeans((Server)lifecycle);  
  46.                 }  
  47.                 if (lifecycle instanceof Service) {  
  48.                     destroyMBeans((Service)lifecycle);  
  49.                 }  
  50.             } catch (MBeanException t) {  
  51.   
  52.                 Exception e = t.getTargetException();  
  53.                 if (e == null) {  
  54.                     e = t;  
  55.                 }  
  56.                 log.error("destroyMBeans: MBeanException", e);  
  57.   
  58.             } catch (Throwable t) {  
  59.   
  60.                 log.error("destroyMBeans: Throwable", t);  
  61.   
  62.             }  
  63.             // FIXME: RMI adaptor should be stopped; however, this is  
  64.             // undocumented in MX4J, and reports exist in the MX4J bug DB that  
  65.             // this doesn't work  
  66.   
  67.         }  
  68.   
  69.         if ((Context.RELOAD_EVENT.equals(event.getType()))  
  70.             || (Lifecycle.START_EVENT.equals(event.getType()))) {  
  71.   
  72.             // Give context a new handle to the MBean server if the  
  73.             // context has been reloaded since reloading causes the  
  74.             // context to lose its previous handle to the server  
  75.             if (lifecycle instanceof StandardContext) {  
  76.                 // If the context is privileged, give a reference to it  
  77.                 // in a servlet context attribute  
  78.                 StandardContext context = (StandardContext)lifecycle;  
  79.                 if (context.getPrivileged()) {  
  80.                     context.getServletContext().setAttribute  
  81.                         (Globals.MBEAN_REGISTRY_ATTR,  
  82.                          MBeanUtils.createRegistry());  
  83.                     context.getServletContext().setAttribute  
  84.                         (Globals.MBEAN_SERVER_ATTR,  
  85.                          MBeanUtils.createServer());  
  86.                 }  
  87.             }  
  88.   
  89.         }  
  90.   
  91.     }  
  92.   
  93.   
  94. }  

 

这里简单介绍一下,Tomcat内部的启动流程, 通过观察者模式与监听器模式来作处理, 组件启动方面,在启动上级组件的同时,先启动下一级组件, (当然,在父组件内部,需要包含它所有子组件引用的一个集合).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值