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)的更多相关文章

  1. Tomcat中组件的生命周期管理公共接口Lifecycle

    Tomcat的组件都会实现一个Lifecycle接口,以方便组件的生命周期的统一管理 interface Lifecycle 组件生命周期中主要的几个方法 增加监听器,事件委托机制 public vo ...

  2. Tomcat源码分析 (三)----- 生命周期机制 Lifecycle

    Tomcat里面有各种各样的组件,每个组件各司其职,组件之间又相互协作共同完成web服务器这样的工程.在这些组件之上,Lifecycle(生命周期机制)至关重要!在学习各个组件之前,我们需要看看Lif ...

  3. How tomcat works(深入剖析tomcat)生命周期Lifecycle

    How Tomcat Works (6)生命周期Lifecycle 总体概述 这一章讲的是tomcat的组件之一,LifeCycle组件,通过这个组件可以统一管理其他组件,可以达到统一启动/关闭组件的 ...

  4. ReactJS入门(二)—— 组件的生命周期

    如果你熟悉avalon,使用过 data-include-rendered 和 data-include-loaded 等回调方法,那么你会很好地理解React组件的各个生命周期. 说白了其实就是Re ...

  5. React Native 中组件的生命周期

    概述 就像 Android 开发中的 View 一样,React Native(RN) 中的组件也有生命周期(Lifecycle).所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命 ...

  6. 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...

  7. reactjs入门到实战(七)---- React的组件的生命周期

    React的组件的生命周期有三个状态分别是:挂载(生产组件示例化.准备挂载到页面.挂载到页面).更新(更新值.更新DOM).和卸载(卸载后). >>>其他     getInitia ...

  8. react.js 从零开始(二)组件的生命周期

    什么是生命周期? 组件本质上是一个状态机,输入确定,输出一定确定. 当状态改变的时候 会触发不同的钩子函数,可以让开发者做出响应.. 一个组件的生命周期可以概括为 初始化:状态下 可以自定义的函数 g ...

  9. Flex组件的生命周期

    组件实例化生命周期描述了用组件类创建组件对象时所发生的一系列步骤,作为生命周期的一部分,flex自动调用组件的的方法,发出事件,并使组件可见. 下面例子用as创建一个btn控件,并将其加入容器中 va ...

随机推荐

  1. CSocket类的使用

    重点介绍一个MFC中CSocket类的使用 1.创建套接字 使用CSocket类创建套接字对象是通过该类的构造函数创建的.其原型如下: CSocket::CSocket(); 例如,用户创建CSock ...

  2. js photoswipe 相册使用 移动pc端均可

    http://photoswipe.com/ 官网  这里使用的是最新 4.1.1版本 http://photoswipe.com/documentation/getting-started.html ...

  3. IWDG—独立看门狗

    本章参考资料:<STM32F4XX 中文参考手册> IWDG 章节.学习本章时,配合<STM32F4XX 中文参考手册> IWDG 章节一起阅读,效果会更佳,特别是涉及到寄存器 ...

  4. kubernetes健康检查

    有时候容器在running的状态,但是里面的服务挂了,这个就难办了,所以k8s提供了一种检查服务是否健康的方法 Liveness Probe的种类: ● ExecAction:在container中执 ...

  5. HTML——图片自动轮换和手动轮换

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Codeforces 558C Amr and Chemistry 暴力 - -

    点击打开链接 Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input stan ...

  7. 监控http服务脚本

    [root@ob1 scripts]# vim test_httpd.sh 1 #!/bin/bash 2 #ss -tlnup|grep :80 >/dev/null 2>&1 ...

  8. 解决spring-boot-starter-logging与log4j冲突

    由于公司在super-bom里配置了检查规则,build项目时遇到错误: [ERROR] [XXX Enforcer Rules] find DuplicateClasses Found in:org ...

  9. java英文缩写

    JSR Java Specification Request Java规范请求 POJO Plain Old Java Object  简单的Java对象

  10. java web中读取properties文件时的路径问题

    在web开发时,难免会有一些固定的参数,我们一般把这些固定的参数存在properties文件中,然后用的时候要读出来.但经常出现一些错误,找不到相应的路径,所以,今天特地讲一些如何正确获得路径. 首先 ...