tomcat学习之生命周期模型

1 概述

1.1 生命周期概述

所有的对象都会经历从创建到消亡的过程。这种例子很多。餐馆老板在每天营业之前,都会提前买菜,切菜(提前炒菜),然后为顾客提供点菜服务,晚上收拾厨房,关门回家。餐馆老板每天的营业过程可以看成是有生命的。起于买菜,止于关门。

Tomcat也有生命,在执行java Bootstrap命令的时候,tomcat类实例被创建,初始化后提供服务;当关闭tomcat服务窗口或者kill掉tomcat进程的时候,tomcat被消亡。

1.2 Tomcat的生命周期
1.2.1 概述

Tomcat中的生命周期接口Lifecycle定义了init\start\stop\destroy方法,分别代表生命周期的不同阶段,个人觉得虽然在接口中没有定义create方法,但是create确是不能不提及的。

下面列出了在tomcat对外提供服务的过程中,涉及到的一些类。这里的类做了一些剪裁,比如:MBean相关的类没有出现在下面的表中。

1.2.2 容器初始类
1.2.2.1 初始类列表

类\接口名(实现类)

描述

Bootstrap

Tomcat启动类

Catalina

Tomcat启动类,被Bootstrap调用

Server(StandardServer)

Tomcat服务器对象

NamingResources

Tomcat用于管理JNDI的内容

Service(StandardService)

Tomcat服务器对外提供的服务

StandardHost

接收特定主机的请求

ContainerBase

基础容器类,StandardHost等都继承于他

LockOutRealm

 

UserDatabaseRealm

 

AccessLogValve

 

ErrorReportValve

 

StandardHostValve

 

Pipeline(StandardPipeline)

 

Connector

Tomcat服务用于接收访问请求的主要类

ProtocolHandler(Http11Protocol)

Tomcat服务用于接收Http请求的处理类

JIoEndpoint

完成具体的接收操作

MapperListener

 
   

这里忽略了一些监听器类,比如:StandardServer的6个监听器类。

1.2.2.2 类设计说明

大部分容器初始类的具体实现都是实现Lifecycle接口。LifecycleBase提供了接口Lifecycle的基本实现,他实现了每一个生命周期接口方法,同时在每个方法中使用“模版模式”,定义了对应方法initInternal\startInternal\stopInternal\destroyInternal,让每一个实现Lifecycle的实现类可以自己做一些具体的事情,看下面的类图可以简单体会到tomcat的类设计:

clip_image002

1.2.3 请求处理类

类\接口名(实现类)

描述

Http11Processor

处理HTTP请求

CoyoteAdapter

Adapter. This represents the entry point in a coyote-based servlet container.

   

2 生命周期阶段

2.1 Create

执行java Bootstrap命令的时候,tomcat开始启动。在启动的时候,Bootstrap和Catalina两个类首先被创建实例。随后的类比如StandardServer、StandardService等等,在tomcat读取解析配置文件server.xml的时候创建,在创建StandardServer的过程中,一些相关的类随之创建,比如:StandardServer的属性globalNamingResources。

提到server.xml,不得不提到一点。它是tomcat的一个很重要的配置文件,没有它,tomcat是启动不了的。server.xml承载了tomcat诸多的重要配置信息。比如:

Ø 通过他可以指定容器初始类的属性,比如StandardServer的port属性和SHUTDOWN属性是通过<Server port="8005" shutdown="SHUTDOWN">指定的;

Ø 通过server.xml中标签的嵌套关系,也给出了容器初始类的包含关系;

Ø server.xml这个文件告诉我们StandardServer是tomcat初始化类的根。

代码方面,除去Bootstrap和Catalina这两个类之外,对其他容器初始类的创建操作都在Catalina的load方法中完成,该方法的作用之一就是通过解析server.xml文件来实例化StandardServer等类。示例代码如下:

public class Catalina {

public void load() {

try {

inputSource.setByteStream(inputStream);

digester.push(this);

digester.parse(inputSource); //这行代码执行完后,容器初始类基本就创建好了。

} catch (Exception e) {

log.warn("Catalina.start using " + getConfigFile() + ": ", e);

return;

}

}

}

说明:上面的代码仅仅是示例代码,是不完整的代码

2.2 Init

tomcat在创建了StandardServer等容器初始类后,紧接着初始化容器。容器初始类的init调用过程可以通过一棵树来展示:

clip_image004

初始化过程中做的事情:

Ø 将初始化对象注册到MBeanServer中,比如:StandardService.init()会调用父类LifecycleMBeanBase的initInternal方法实现MBean的注册,示例代码如下:

public abstract class LifecycleMBeanBase extends LifecycleBase

implements MBeanRegistration {

protected void initInternal() throws LifecycleException {

if (oname == null) {

mserver = Registry.getRegistry(null, null).getMBeanServer();

oname = register(this, getObjectNameKeyProperties());

}

}

}

Ø 除了注册对象到MBeanServer中,位于树上层的初始化类,还会调用下层初始化类的init方法;

Ø 位于树底层的初始化类,通常还会初始化自身的一些属性,比如:JIOEndpoint的serverSocket就是在初始化的时候被实例化的,该过程通过JIOEndpoint的父类AbstractEndpoint的init方法调用JIOEndpoint重写的bind方法实现,示例代码如下:

public class JIoEndpoint extends AbstractEndpoint {

@Override

public void bind() throws Exception {

// Initialize thread count defaults for acceptor

if (acceptorThreadCount == 0) {

acceptorThreadCount = 1;

}

// Initialize maxConnections

if (getMaxConnections() == 0) {

// User hasn't set a value - use the default

setMaxConnections(getMaxThreadsExecutor(true));

}

if (serverSocketFactory == null) {

if (isSSLEnabled()) {

serverSocketFactory =

handler.getSslImplementation().getServerSocketFactory(this);

} else {

serverSocketFactory = new DefaultServerSocketFactory(this);

}

}

if (serverSocket == null) {

try {

if (getAddress() == null) {

serverSocket = serverSocketFactory.createSocket(getPort(),

getBacklog());

} else {

serverSocket = serverSocketFactory.createSocket(getPort(),

getBacklog(), getAddress());

}

} catch (BindException orig) {

String msg;

if (getAddress() == null)

msg = orig.getMessage() + " <null>:" + getPort();

else

msg = orig.getMessage() + " " +

getAddress().toString() + ":" + getPort();

BindException be = new BindException(msg);

be.initCause(orig);

throw be;

}

}

}

}

2.3 Start

重新审视生命周期的create和init接口,他们在做同一件事情,实例化类对象,区别在于,create阶段实例化的对象大部分是容器初始化类,init方法也会实例化一些类,但是这些类往往作为容器初始类的属性存在。

在看完init方法后,我们可以来研究下start接口的调用树,如下图:

clip_image006

几点说明如下:

Ø 该树最上层的方法调用发生在类Catalina的start方法中,Catalina在执行来了方法load后,调用方法start;

Ø 该树中start方法的调用树有个规律,大部分类的start方法只是为了调用下层类的start方法;

Ø 最终起作用的AbstractEndpoint.start()会启用一个ServerSocket,其作用用来监听浏览器或者其他web客户端发到tomcat的http请求

至此,tomcat就可以对外提供服务了。

2.4 Stop\Destroy

通过执行java Bootstrap stop命令,可以触发Catalina类的stop方法的调用,Catalina的stop方法依次完成生命周期方法stop和destroy方法的调用。这两个方法的设计意图在于释放资源,比如清空NamingResource中的对象、在start方法中启动的serverSocket。

方法的调用树,跟init和start类似,这里不再赘述。

转载于:https://my.oschina.net/psuyun/blog/298500

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值