首页 > 代码库 > Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)
Tomcat 8(七)解读Bootstrap介绍过。运行startup.bat。将引发Tomcat一连串组件的启动。事实上这一连串启动是通过组件的生命周期(Lifecycle)实现的
今天来看看Lifecycle设计。解读Lifecycle。涉及到例如以下几个类
Lifecycle、LifecycleState、LifecycleEvent、LifecycleListener(位于org.apache.catalina)
LifecycleBase、LifecycleSupport、LifecycleMBeanBase(位于org.apache.catalina.util)
Lifecycle接口
package org.apache.catalina; public interface Lifecycle { public static final String BEFORE_INIT_EVENT = "before_init"; public static final String AFTER_INIT_EVENT = "after_init"; 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 static final String AFTER_DESTROY_EVENT = "after_destroy"; public static final String BEFORE_DESTROY_EVENT = "before_destroy"; public static final String PERIODIC_EVENT = "periodic"; public static final String CONFIGURE_START_EVENT = "configure_start"; public static final String CONFIGURE_STOP_EVENT = "configure_stop"; public void addLifecycleListener(LifecycleListener listener); public LifecycleListener[] findLifecycleListeners(); public void removeLifecycleListener(LifecycleListener listener); public void init() throws LifecycleException; public void start() throws LifecycleException; public void stop() throws LifecycleException; public void destroy() throws LifecycleException; public LifecycleState getState(); public String getStateName(); }
Lifecycle接口的作用
定义了事件类型(静态常量字符串)
定义了init/start/stop/destroy方法,即组件初始化/启动/停止/销毁
定义了addLifecycleListener/findLifecycleListeners/removeLifecycleListener方法,即加入/获取/移除监听器(监听器主要监听启动、停止动作)
LifecycleState枚举
package org.apache.catalina; public enum LifecycleState { NEW(false, null), INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT), INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT), STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT), STARTING(true, Lifecycle.START_EVENT), STARTED(true, Lifecycle.AFTER_START_EVENT), STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT), STOPPING(false, Lifecycle.STOP_EVENT), STOPPED(false, Lifecycle.AFTER_STOP_EVENT), DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT), DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT), FAILED(false, null), MUST_STOP(true, null), MUST_DESTROY(false, null); private final boolean available; private final String lifecycleEvent; private LifecycleState(boolean available, String lifecycleEvent) { this.available = available; this.lifecycleEvent = lifecycleEvent; } public boolean isAvailable() { return available; } public String getLifecycleEvent() { return lifecycleEvent; } }
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通知给LifecycleListener,LifecycleListener会做出对应处理
LifecycleBase
LifecycleBase实现了Lifecycle接口,加入了几个新的方法如setStateInternal(更新组件状态)、fireLifecycleEvent(触发LifecycleEvent)
加入了四个抽象方法initInternal、startInternal、stopInternal、destroyInternal
LifecycleBase内初始化了LifecycleSupport、LifecycleState
private final LifecycleSupport lifecycle = new LifecycleSupport(this); private volatile LifecycleState state = LifecycleState.NEW;
以下来看看LifecycleBase的init方法的逻辑(start/stop/destroy的逻辑与init类似)
public final synchronized void init() throws LifecycleException { //查看组件状态是否为LifecycleState.NEW if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } //更新组件状态LifecycleState.INITIALIZING setStateInternal(LifecycleState.INITIALIZING, null, false); try { //调用initInternal initInternal(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException( sm.getString("lifecycleBase.initFail",toString()), t); } //更新组件状态为LifecycleState.INITIALIZED。到此初始化完毕 setStateInternal(LifecycleState.INITIALIZED, null, false); }
注意init方法内部又调用了initInternal方法
LifecycleMBeanBase
LifecycleMBeanBase继承LifecycleBase,LifecycleMBeanBase内又加入了一些新的方法
StandardServer、StandardService等组件继承LifecycleMBeanBase,并重写initInternal、startInternal、stopInternal、destroyInternal方法
以下来看看StandardServer的initInternal方法
protected void initInternal() throws LifecycleException { //调用父类(LifecycleMBeanBase)的initInternal方法 super.initInternal(); onameStringCache = register(new StringCache(), "type=StringCache"); // Register the MBeanFactory MBeanFactory factory = new MBeanFactory(); factory.setContainer(this); onameMBeanFactory = register(factory, "type=MBeanFactory"); // Register the naming resources globalNamingResources.init(); // Populate the extension validator with JARs from common and shared // class loaders if (getCatalina() != null) { ClassLoader cl = getCatalina().getParentClassLoader(); // Walk the class loader hierarchy. Stop at the system class loader. // This will add the shared (if present) and common class loaders while (cl != null && cl != ClassLoader.getSystemClassLoader()) { if (cl instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) cl).getURLs(); for (URL url : urls) { if (url.getProtocol().equals("file")) { try { File f = new File (url.toURI()); if (f.isFile() && f.getName().endsWith(".jar")) { ExtensionValidator.addSystemResource(f); } } catch (URISyntaxException e) { // Ignore } catch (IOException e) { // Ignore } } } } cl = cl.getParent(); } } //Server调用其子组件(Service)的init方法,Service在初始化过程中又会调用其子组件的init方法 for (int i = 0; i < services.length; i++) { services[i].init(); } }
当Catalina调用StandardServer的init方法时,因为StandardServer未重写init方法,因此将使用LifecycleBase的init方法。当运行到initInternal()时,因为StandardServer重写了initInternal方法,因此将使用StandardServer的initInternal方法(应用了多态。每一个组件的initInternal方法包括其自己定义逻辑)
通过Lifecycle。Tomcat启动最顶层组件(Server)。就可以启动全部组件
Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)