五月开的草本花有什么品种?

小说:五月开的草本花有什么品种?作者:通宗密更新时间:2019-04-21字数:91724

写在前面的话:读Tomcat源码也有段时间了,大领悟谈不上。一些小心得记录下来,供大家参考相护学习。

一、启动流程

Tomcat启动首先需要熟悉的是它的启动流程。和初学者第一天开始写Hello World一样,Tomcat的启动也依赖main方法。

 1 /*
 2  * org.apache.catalina.startup.Bootstrap
 3  */
 4 if (daemon == null) {
 5     Bootstrap bootstrap = new Bootstrap(); // 实例对象
 6     try {
 7         bootstrap.init(); // 初始化
 8     } catch (Throwable t) {
 9         handleThrowable(t);
10         return;
11     }
12     daemon = bootstrap;
13 } else {
14     Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
15 }

实例化Bootstrap之后,首先需要对它初始化。初始化的流程很长,但是省略掉细节其实就是做了两件事:

(1)为当前线程创建类加载器:

initClassLoaders()

 

(2)通过反射实例化一个Catalina对象(Tomcat组件的实际管理者):

Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();

 

 初始化以后daemon和catalinaDaemon就完成了赋值。继续main方法往下

 1 String command = "start";
 2 if (args.length > 0) {
 3     command = args[args.length - 1];
 4 }
 5 if (command.equals("startd")) {
 6     args[args.length - 1] = "start";
 7     daemon.load(args); // 加载
 8     daemon.start(); // 启动
 9 } else if (command.equals("stopd")) {
10     args[args.length - 1] = "stop";
11     daemon.stop();
12 } else if (command.equals("start")) {
13     daemon.setAwait(true);
14     daemon.load(args);
15     daemon.start();
16 } else if (command.equals("stop")) {
17     daemon.stopServer(args);
18 }

首先执行加载,依然是使用反射调用Catalina对象的load()方法。方法里面的代码很多第一次看的同学肯定会有点蒙,仔细分析一下:

(1)读取conf/server.xml文件并解析InputStream:

Digester是一个xml文件解析工具,目前属于Apache的Jakarta项目。使用Digester解析xml文件代码量少也非常简单。

(2)初始化Server

Server serv = getServer();
serv.init();

 

接下来我们看看server.xml的文档结构,里面包含了几个重要的节点:Server、Listener、Service、Connector、Engine、Realm、Host。初始化的过程其实就是将这些节点所代表的对象逐一初始化。Server是其它节点的根节点,所以首先对它执行init()操作。

二、生命周期管理

Tomcat中的许多对象都实现了Lifecycle接口,里面定义了12个状态,类关系图如下:

LifecycleBase实现了Lifecycle并引入LifecycleState和LifecycleSupport,LifecycleState是一个枚举类,将12个状态除NEW和FAILED以外分别将状态和事件对应,并通过事件触发监听器。LifecycleSupport集中管理各种监听器。Tomcat通过4个方法管理这些状态:init() 、start()、stop()、destroy(),而LifecycleBase实现了init() 、start()、stop()、destroy()又暴露了4个接口initInternal()、startInternal()、stopInternal()、destroyInternal()。所有生命周期对象都需要实现以上4个方法,是设计模式中的模板模式。

初略分析了一下Tomcat对于组件的管理方式,接下来再回到Catalina的load()方法。方法中通过getServer()获取StandardServer实例,并执行initInternal()方法。在server.xml配置文件中,server节点可以包含多个service

for (int i = 0; i < services.length; i++) {
    services[i].init(); // 初始化StandardService
}

在StandardService的initInternal()方法中继续初始化Connector和Executor,重点代码如下:

 1 synchronized (connectorsLock) {
 2     for (Connector connector : connectors) {
 3         try {
 4             connector.init();
 5         } catch (Exception e) {
 6             String message = sm.getString(
 7                     "standardService.connector.initFailed", connector);
 8             log.error(message, e);
 9 
10             if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
11                 throw new LifecycleException(message);
12         }
13     }
14 }

 

当所有组件初始化完成之后执行启动流程:

 1 try {
 2     // getServer().start();
 3     Server srv = getServer();
 4     srv.start(); // 启动流程...
 5 } catch (LifecycleException e) {
 6     log.fatal(sm.getString("catalina.serverStartFail"), e);
 7     try {
 8         getServer().destroy();
 9     } catch (LifecycleException e1) {
10         log.debug("destroy() failed for failed Server ", e1);
11     }
12     return;
13 }

和initInternal()流程类似,startInternal()方法也是逐步调用,就不在文章中一一分析了。感兴趣的同学要想深入探究请通过源码debug分析。

 

总结:Tomcat启动流程实质上就是对各个生命周期组件的管理并通过Digester解析xml文件,这些组件在不同的生命周期状态又分别对应不同的响应事件,监听器通过响应事件驱动也方便了开发者的二次扩展值得认真学习。

当前文章:http://emigration.net.cn/knx1s44sjr.html

发布时间:2019-04-21 07:31:57

地径8公分桃树多少钱一棵? 10公分榆叶梅批发基地在哪里? 美人梅夏季能栽植吗? 为什么金娃娃萱草会这么的吃香,是有一定理由的哦 直径10公分垂柳多少钱一棵? 1公分紫竹哪家报价最低? 小叶紫薇1.2米高价格哪里最低? 新疆可以栽植玉簪吗? 小叶黄杨移栽成活率高吗? 欧月月季苗的价格哪里最低?

55206 27079 11865 73527 15016 70290 79837 47658 49962 36381 21170 12771 93487 22756 47189 10253 55970 92233 86827 59144 41187 42058 46735

我要说两句: (0人参与)

发布