浅读tomcat架构设计和tomcat启动过程(1)

  https://www.cnblogs.com/piaomiaohongchen/p/14977272.html

  tomcat通过org.apache.catalina.Lifecycle接口统一管理生命周期,所有有生命周期的组建都要实现Lifecycle接口.

  通过反射加载查看代码:

  Lifecycle的接口方法有很多,简单解读下:  

  (1)定义13个String类型的常量,不同的常量,代表不同的状态信息

  

  (2)定义了3个管理监听器的方法:

  分别是添加,监听和删除

    void addLifecycleListener(LifecycleListener var1);

    LifecycleListener[] findLifecycleListeners();

    void removeLifecycleListener(LifecycleListener var1);

  

  

  (3)定义了四个生命周期方法:

    分别是初始化,开启,停止,销毁:

void init() throws LifecycleException;

void start() throws LifecycleException;

void stop() throws LifecycleException;

void destroy() throws LifecycleException;

  

 (4)定义了获取状态的两个方法:

LifecycleState getState();

String getStateName();

  

  其中getState的返回类是enum类型,getStateName返回的类型是String类型

  Lifecycle接口的默认实现是org.apache.catalina.util.LifecycleBase,LifecycleBase为Lifecycle里的接口方法提供了默认实现.

  先看看三个管理监听器方法的具体实现:

  org.apache.catalina.util.LifecycleBase:   

   public void addLifecycleListener(LifecycleListener listener) {
this.lifecycle.addLifecycleListener(listener);
} public LifecycleListener[] findLifecycleListeners() {
return this.lifecycle.findLifecycleListeners();
} public void removeLifecycleListener(LifecycleListener listener) {
this.lifecycle.removeLifecycleListener(listener);
}

  发现在方法内部都是调用的lifecycle.**()方法

  而this.lifecycle的定义是

    

 private final LifecycleSupport lifecycle = new LifecycleSupport(this);

    

  三个监听器方法都是调用的是LifecycleSupport类的对象方法

  LifecycleSupport监听器是通过一个数组属性listeners来保存的,代码如下:

  org.apache.catalina.util.LifecycleSupport:

private final Object listenersLock = new Object();

    public LifecycleSupport(Lifecycle lifecycle) {
this.lifecycle = lifecycle;
} public void addLifecycleListener(LifecycleListener listener) {
synchronized(this.listenersLock) {
LifecycleListener[] results = new LifecycleListener[this.listeners.length + 1]; for(int i = 0; i < this.listeners.length; ++i) {
results[i] = this.listeners[i];
} results[this.listeners.length] = listener;
this.listeners = results;
}
} public LifecycleListener[] findLifecycleListeners() {
return this.listeners;
} public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this.lifecycle, type, data);
LifecycleListener[] interested = this.listeners; for(int i = 0; i < interested.length; ++i) {
interested[i].lifecycleEvent(event);
} } public void removeLifecycleListener(LifecycleListener listener) {
synchronized(this.listenersLock) {
int n = -1; for(int i = 0; i < this.listeners.length; ++i) {
if (this.listeners[i] == listener) {
n = i;
break;
}
} if (n >= 0) {
LifecycleListener[] results = new LifecycleListener[this.listeners.length - 1];
int j = 0; for(int i = 0; i < this.listeners.length; ++i) {
if (i != n) {
results[j++] = this.listeners[i];
}
} this.listeners = results;
}
}
}

  这三个方法的实现非常简单,就是新增/删除/查找等动作的实现,就是对listener属性做操作

    其中的fireLifecycleEvent函数的含义是用于遍历所有监听器进行处理  

    

  

  四个生命周期的方法:

    先看init方法,让我们回到之前的org.apache.catalina.util.LifecycleBase类:

    org.apache.catalina.util.LifecycleBase:

    

public final synchronized void init() throws LifecycleException {
if (!this.state.equals(LifecycleState.NEW)) {
this.invalidTransition("before_init");
} this.setStateInternal(LifecycleState.INITIALIZING, (Object)null, false); try {
this.initInternal();
} catch (Throwable var2) {
ExceptionUtils.handleThrowable(var2);
this.setStateInternal(LifecycleState.FAILED, (Object)null, false);
throw new LifecycleException(sm.getString("lifecycleBase.initFail", new Object[]{this.toString()}), var2);
} this.setStateInternal(LifecycleState.INITIALIZED, (Object)null, false);
}

  代码很简单,就是先判断state是否是LifecycleState.NEW,如果是NEW的话就设置为state状态为LifecycleState.INITIALIZING,如果不是,就抛出异常,所以init初始化的时候必须是LifecycleState.NEW

  接着往下看,看start方法:

     

public final synchronized void start() throws LifecycleException {
if (!LifecycleState.STARTING_PREP.equals(this.state) && !LifecycleState.STARTING.equals(this.state) && !LifecycleState.STARTED.equals(this.state)) {
if (this.state.equals(LifecycleState.NEW)) {
this.init();
} else if (this.state.equals(LifecycleState.FAILED)) {
this.stop();
} else if (!this.state.equals(LifecycleState.INITIALIZED) && !this.state.equals(LifecycleState.STOPPED)) {
this.invalidTransition("before_start");
} this.setStateInternal(LifecycleState.STARTING_PREP, (Object)null, false); try {
this.startInternal();
} catch (Throwable var2) {
ExceptionUtils.handleThrowable(var2);
this.setStateInternal(LifecycleState.FAILED, (Object)null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", new Object[]{this.toString()}), var2);
} if (!this.state.equals(LifecycleState.FAILED) && !this.state.equals(LifecycleState.MUST_STOP)) {
if (!this.state.equals(LifecycleState.STARTING)) {
this.invalidTransition("after_start");
} this.setStateInternal(LifecycleState.STARTED, (Object)null, false);
} else {
this.stop();
} } else {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()}), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()}));
} }
}

  start方法做的事情比int方法多一些,判断state状态,如果是LifecycleState.NEW,就初始化,根据不同的state状态,进不同的逻辑,然后设置状态调用setStateInternal方法:

    跟进方法:

    还是在org.apache.catalina.util.LifecycleBase:

private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", new Object[]{this, state}));
} if (check) {
if (state == null) {
this.invalidTransition("null");
return;
} if (state != LifecycleState.FAILED && (this.state != LifecycleState.STARTING_PREP || state != LifecycleState.STARTING) && (this.state != LifecycleState.STOPPING_PREP || state != LifecycleState.STOPPING) && (this.state != LifecycleState.FAILED || state != LifecycleState.STOPPING)) {
this.invalidTransition(state.name());
}
} this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
this.fireLifecycleEvent(lifecycleEvent, data);
} }

  这个方法先是判断check,然后判断state是否为null,是null就抛出异常,最后将state赋值给state变量,然后调用getLifecycleEvent方法处理事件,下面的this.fireLifecycleEvent(lifecycleEvent, data);实际上调用的是LifecycleSupport类的方法:

  跟进这个方法看下:

    

 protected void fireLifecycleEvent(String type, Object data) {
this.lifecycle.fireLifecycleEvent(type, data);
}

   继续往上回溯:

  

 private final LifecycleSupport lifecycle = new LifecycleSupport(this);

  同理stop和destroy方法逻辑类似

  获取状态的两个方法  

  还是在org.apache.catlina.util.LifecycleBase:

  在生命周期的相应方法中获取state属性,直接返回的state

  

public LifecycleState getState() {
return this.state;
} public String getStateName() {
return this.getState().toString();
}

    

    

浅读tomcat架构设计之tomcat生命周期(2)的更多相关文章

  1. 浅读tomcat架构设计之tomcat容器Container(3)

    浅读tomcat架构设计和tomcat启动过程(1) https://www.cnblogs.com/piaomiaohongchen/p/14977272.html 浅读tomcat架构设计之tom ...

  2. 浅读tomcat架构设计和tomcat启动过程(1)

    一图甚千言,这张图真的是耽搁我太多时间了: 下面的tomcat架构设计代码分析,和这张图息息相关. 使用maven搭建本次的环境,贴出pom.xml完整内容: <?xml version=&qu ...

  3. Tomcat详解系列(2) - 理解Tomcat架构设计

    Tomcat - 理解Tomcat架构设计 前文我们已经介绍了一个简单的Servlet容器是如何设计出来,我们就可以开始正式学习Tomcat了,在学习开始,我们有必要站在高点去看看Tomcat的架构设 ...

  4. 浅读tomcat架构设计之Pipeline-Valve管道(4)

    tomcat Container容器处理请求是使用Pipeline-Valve管道来处理的,后续写的tomcat内存马,和他紧密结合 Pipeline-Valve是责任链模式,责任链模式是指在一个请求 ...

  5. Tomcat架构解析(一)-----Tomcat总体架构

    Tomcat是非常常用的应用服务器,了解Tomcat的总体架构以及实现细节,对于理解整个java web也是有非常大的帮助. 一.Server   1.最简单的服务器结构 最简单的服务器结构如图所示: ...

  6. Tomcat架构解析(五)-----Tomcat的类加载机制

    类加载器就是根据类的全限定名(例如com.ty.xxx.xxx)来获取此类的二进制字节流的代码模块,从而程序可以自己去获取到相关的类. 一.java中的类加载器   1.类加载器类别 java中的类加 ...

  7. 浅谈Android的Activity运行流程(生命周期)

    关于Android的Activity运行流程,我们可以写一些程序来直观的查看Activity的运行流程.在这里我们使用Log工具来获取Activity运行日志.假如我们新建一个Android项目,Pr ...

  8. 【tomcat】servlet原理及其生命周期

    1.什么是servlet? Servlet(Servlet Applet),全称Java Servlet,是用Java编写的服务器端程序.而这些Servlet都要实现Servlet这个接口.其主要功能 ...

  9. tomcat源码阅读之生命周期(LifeCycle)

    一.事件机制流程: 1.     当外部事件源发生事件(比如点击了按钮,数据发生改变更新等)时,事件源将事件封装成事件对象Event: 2.     将事件对象交由对应的事件派发器Dispatcher ...

随机推荐

  1. Xshell 远程使用vim打开文件不能使用右键复制粘贴(右键显示可视)的问题

    Xshell 远程使用vim打开文件不能使用右键复制粘贴(右键显示可视)的问题 Debian9.4系统不能再VIM打开文件界面不能使用右键复制粘贴 root@debian:~# vim /usr/sh ...

  2. Jenkins远程代码执行漏洞

    于一个月前,进行服务器巡检时,发现服务器存在不明进程,并且以Jenkins用户身份来运行.当时进行了处理并修复了漏洞.在此补上修复过程 第一反应是Jenkins存在漏洞,于是Google Jenkin ...

  3. Linux中级之windows下使用curl命令(cmd命令行)

    在官网下载工具包:http://curl.haxx.se/download.html(根据自己电脑系统位数选择) 使用方式一:在curl.exe目录中使用 解压下载后的压缩文件,通过cmd命令进入到c ...

  4. 网上的说TB6560存在的问题

    https://www.amobbs.com/thread-5506456-2-1.html

  5. Linux系统添加永久静态路由的方法(包含Centos7)

    一.使用route命令添加 使用route 命令添加的路由,机器重启或者网卡重启后路由就失效了,方法:A.添加到主机的路由# route add –host 192.168.1.10 dev eth0 ...

  6. Redis()- 布隆过滤器

    一.布隆过滤器 布隆过滤器:一种数据结构.由二进制数组(很长的二进制向量)组成的.布隆过滤器可以用于检索一个元素是否在一个集合中.它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识 ...

  7. 行者APP适配国外环境问题解决

    (本文1151字,阅读约5分钟) 玩骑行的同伴都知道,长途骑行,第一需要好的硬件,如大腿发动机.车子.装备等:二是需要好的软件,如意志.有氧能力.骑行app等. 到雅加达后,才发现在国内用了几年的黑鸟 ...

  8. Auto ML自动特征工程

    Auto ML自动特征工程 特征工程是在做机器学习训练的过程中必不可少的环节,特征工程就是找出对模型结果有益的特征交叉关系,通常特征工程需要耗费算法工程师大量的精力去尝试.针对这样的场景,PAI推出智 ...

  9. Megengine量化

    Megengine量化 量化指的是将浮点数模型(一般是32位浮点数)的权重或激活值用位数更少的数值类型(比如8位整数.16位浮点数)来近似表示的过程. 量化后的模型会占用更小的存储空间,还能够利用许多 ...

  10. Python批量重命名 工具贴(一)

    说明 由于在处理图片数据和其他数据时,经常需要对数据进行批量重命名操作,每次使用时都需要重写,非常不便,因此记录下重命名代码方便后续使用. 文件结构说明 参数说明: path为输入路径 image_t ...