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),即可启动所有组件