Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)

时间:2021-01-01 08:59:50

Tomcat 8(七)解读Bootstrap介绍过,执行startup.bat,将引发Tomcat一连串组件的启动。其实这一连串启动是通过组件的生命周期(Lifecycle)实现的

今天来看看Lifecycle设计。解读Lifecycle,涉及到如下几个类

Lifecycle、LifecycleState、LifecycleEvent、LifecycleListener(位于org.apache.catalina)

LifecycleBase、LifecycleSupport、LifecycleMBeanBase(位于org.apache.catalina.util)

Lifecycle接口

[java]  view plain  copy   Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle) Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
  1. package org.apache.catalina;  
  2.   
  3. public interface Lifecycle {  
  4.   
  5.     public static final String BEFORE_INIT_EVENT = "before_init";  
  6.     public static final String AFTER_INIT_EVENT = "after_init";  
  7.     public static final String START_EVENT = "start";  
  8.     public static final String BEFORE_START_EVENT = "before_start";  
  9.     public static final String AFTER_START_EVENT = "after_start";  
  10.     public static final String STOP_EVENT = "stop";  
  11.     public static final String BEFORE_STOP_EVENT = "before_stop";  
  12.     public static final String AFTER_STOP_EVENT = "after_stop";  
  13.     public static final String AFTER_DESTROY_EVENT = "after_destroy";  
  14.     public static final String BEFORE_DESTROY_EVENT = "before_destroy";  
  15.     public static final String PERIODIC_EVENT = "periodic";  
  16.     public static final String CONFIGURE_START_EVENT = "configure_start";  
  17.     public static final String CONFIGURE_STOP_EVENT = "configure_stop";  
  18.   
  19.     public void addLifecycleListener(LifecycleListener listener);  
  20.   
  21.     public LifecycleListener[] findLifecycleListeners();  
  22.   
  23.     public void removeLifecycleListener(LifecycleListener listener);  
  24.   
  25.     public void init() throws LifecycleException;  
  26.   
  27.     public void start() throws LifecycleException;  
  28.   
  29.     public void stop() throws LifecycleException;  
  30.   
  31.     public void destroy() throws LifecycleException;  
  32.   
  33.     public LifecycleState getState();  
  34.   
  35.     public String getStateName();  
  36. }  

Lifecycle接口的作用

定义了事件类型(静态常量字符串)

定义了init/start/stop/destroy方法,即组件初始化/启动/停止/销毁

定义了addLifecycleListener/findLifecycleListeners/removeLifecycleListener方法,即添加/获取/移除监听器(监听器主要监听启动、停止动作)

LifecycleState枚举

[java]  view plain  copy   Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle) Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
  1. package org.apache.catalina;  
  2.   
  3. public enum LifecycleState {  
  4.     NEW(falsenull),  
  5.     INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),  
  6.     INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),  
  7.     STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),  
  8.     STARTING(true, Lifecycle.START_EVENT),  
  9.     STARTED(true, Lifecycle.AFTER_START_EVENT),  
  10.     STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),  
  11.     STOPPING(false, Lifecycle.STOP_EVENT),  
  12.     STOPPED(false, Lifecycle.AFTER_STOP_EVENT),  
  13.     DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),  
  14.     DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),  
  15.     FAILED(falsenull),  
  16.     MUST_STOP(truenull),  
  17.     MUST_DESTROY(falsenull);  
  18.   
  19.     private final boolean available;  
  20.     private final String lifecycleEvent;  
  21.   
  22.     private LifecycleState(boolean available, String lifecycleEvent) {  
  23.         this.available = available;  
  24.         this.lifecycleEvent = lifecycleEvent;  
  25.     }  
  26.   
  27.     public boolean isAvailable() {  
  28.         return available;  
  29.     }  
  30.   
  31.     public String getLifecycleEvent() {  
  32.         return lifecycleEvent;  
  33.     }  
  34. }  

LifecycleState定义了组件状态的枚举。LifecycleState包含两个属性:available、lifecycleEvent

available(boolean)-处于此状态的组件是否可以执行public方法(get/set方法除外),是否可以获取lifecycleEvent值

lifecycleEvent(String)-处于此状态的组件正进行的事件

LifecycleEvent

LifecycleEvent是个实体类,包含三个属性lifecycle、type、data

lifecycle(Lifecycle)-将触发事件的组件

(注意:每个组件都可以向上转成Lifecycle类型,因为组件继承LifecycleMBeanBase,而LifecycleMBeanBase继承LifecycleBase,而LifecycleBase是Lifecycle的一种实现)

type(String)-事件类型

data(String)-事件数据

LifecycleSupport

LifecycleSupport将组件正在进行的LifecycleEvent通知给监听器(LifecycleListener)

LifecycleListener

监听特定事件,并做出相应处理

AprLifecycleListener(org.apache.catalina.core)就是LifecycleListener的一种实现

组件更新状态时,如果组件当前状态的lifecycleEvent不为空,LifecycleSupport会将 lifecycleEvent通知给LifecycleListenerLifecycleListener会做出相应处理 

LifecycleBase

LifecycleBase实现了Lifecycle接口,添加了几个新的方法如setStateInternal(更新组件状态)fireLifecycleEvent(触发LifecycleEvent)

添加了四个抽象方法initInternal、startInternal、stopInternal、destroyInternal

LifecycleBase内初始化了LifecycleSupport、LifecycleState

[java]  view plain  copy   Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle) Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
  1. private final LifecycleSupport lifecycle = new LifecycleSupport(this);  
  2. private volatile LifecycleState state = LifecycleState.NEW;  

下面来看看LifecycleBase的init方法的逻辑(start/stop/destroy的逻辑与init类似)

[java]  view plain  copy   Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle) Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
  1. public final synchronized void init() throws LifecycleException {  
  2.     //查看组件状态是否为LifecycleState.NEW  
  3.     if (!state.equals(LifecycleState.NEW)) {  
  4.         invalidTransition(Lifecycle.BEFORE_INIT_EVENT);  
  5.     }  
  6.     //更新组件状态LifecycleState.INITIALIZING  
  7.     setStateInternal(LifecycleState.INITIALIZING, nullfalse);  
  8.   
  9.     try {  
  10.     //调用initInternal  
  11.         initInternal();  
  12.     } catch (Throwable t) {  
  13.         ExceptionUtils.handleThrowable(t);  
  14.         setStateInternal(LifecycleState.FAILED, nullfalse);  
  15.         throw new LifecycleException(  
  16.                 sm.getString("lifecycleBase.initFail",toString()), t);  
  17.     }  
  18.       
  19.     //更新组件状态为LifecycleState.INITIALIZED。到此初始化完成  
  20.     setStateInternal(LifecycleState.INITIALIZED, nullfalse);  
  21. }  

注意init方法内部又调用了initInternal方法

LifecycleMBeanBase

LifecycleMBeanBase继承LifecycleBase,LifecycleMBeanBase内又添加了一些新的方法

StandardServerStandardService等组件继承LifecycleMBeanBase,并重写initInternalstartInternalstopInternaldestroyInternal方法

下面来看看StandardServer的initInternal方法

[java]  view plain  copy   Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle) Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
  1. protected void initInternal() throws LifecycleException {  
  2.     //调用父类(LifecycleMBeanBase)的initInternal方法  
  3.     super.initInternal();  
  4.       
  5.     onameStringCache = register(new StringCache(), "type=StringCache");  
  6.   
  7.     // Register the MBeanFactory  
  8.     MBeanFactory factory = new MBeanFactory();  
  9.     factory.setContainer(this);  
  10.     onameMBeanFactory = register(factory, "type=MBeanFactory");  
  11.   
  12.     // Register the naming resources  
  13.     globalNamingResources.init();  
  14.   
  15.     // Populate the extension validator with JARs from common and shared  
  16.     // class loaders  
  17.     if (getCatalina() != null) {  
  18.         ClassLoader cl = getCatalina().getParentClassLoader();  
  19.         // Walk the class loader hierarchy. Stop at the system class loader.  
  20.         // This will add the shared (if present) and common class loaders  
  21.         while (cl != null && cl != ClassLoader.getSystemClassLoader()) {  
  22.             if (cl instanceof URLClassLoader) {  
  23.                 URL[] urls = ((URLClassLoader) cl).getURLs();  
  24.                 for (URL url : urls) {  
  25.                     if (url.getProtocol().equals("file")) {  
  26.                         try {  
  27.                             File f = new File (url.toURI());  
  28.                             if (f.isFile() &&  
  29.                                     f.getName().endsWith(".jar")) {  
  30.                                 ExtensionValidator.addSystemResource(f);  
  31.                             }  
  32.                         } catch (URISyntaxException e) {  
  33.                             // Ignore  
  34.                         } catch (IOException e) {  
  35.                             // Ignore  
  36.                         }  
  37.                     }  
  38.                 }  
  39.             }  
  40.             cl = cl.getParent();  
  41.         }  
  42.     }  
  43.     //Server调用其子组件(Service)的init方法,Service在初始化过程中又会调用其子组件的init方法  
  44.     for (int i = 0; i < services.length; i++) {  
  45.         services[i].init();  
  46.     }  
  47. }  

当Catalina调用StandardServer的init方法时,由于StandardServer未重写init方法,因此将使用LifecycleBase的init方法,当执行到initInternal()时,由于StandardServer重写了initInternal方法,因此将使用StandardServer的initInternal方法(应用了多态。每个组件的initInternal方法包含其自定义逻辑)

通过Lifecycle,Tomcat启动最顶层组件(Server),即可启动所有组件