博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Tomcat 源码分析(一)——启动与生命周期组件
阅读量:5010 次
发布时间:2019-06-12

本文共 3546 字,大约阅读时间需要 11 分钟。

写在前面的话:读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文件,这些组件在不同的生命周期状态又分别对应不同的响应事件,监听器通过响应事件驱动也方便了开发者的二次扩展值得认真学习。

转载于:https://www.cnblogs.com/learnhow/p/8047869.html

你可能感兴趣的文章
java中的类型安全问题-Type safety: Unchecked cast from Object to ...
查看>>
如何解决最后一个尾注引用显示与致谢混为一谈的问题-下
查看>>
Java Socket编程 - 基于TCP方式的二进制文件传输【转】http://blog.csdn.net/jia20003/article/details/8248221...
查看>>
阅读之https及加密原理
查看>>
HDOJ4550 卡片游戏 随便销毁内存的代价就是wa//string类的一些用法
查看>>
css文本样式text、字体样式font
查看>>
洛谷 P1020 导弹拦截(LIS)
查看>>
python判断图片是否损坏
查看>>
MySQL服务启动:某些服务在未由其他服务或程序使用时将自动停止
查看>>
软件工程第四周作业 - 单元测试
查看>>
KNN与SVM对比&SVM与逻辑回归的对比
查看>>
php 现在拓展地址
查看>>
【Java并发编程】之十六:深入Java内存模型——happen-before规则及其对DCL的分析(含代码)...
查看>>
团队个人冲刺第三天
查看>>
unit
查看>>
2017-10-17 NOIP模拟赛2
查看>>
How to install ia32-libs in Ubuntu 14.04 LTS (Trusty Tahr)
查看>>
ACM/ICPC 之 模拟 (HNUOJ 13391-换瓶模拟)
查看>>
JavaWeb学习——JSP基础
查看>>
Eclipse tomcat server 无法添加项目
查看>>