(四) Tomcat 源码系列之 Tomcat 启动流程

一切的 Java 程序入口都是 main 方法, Tomcat 的启动类是哪个呢?

直接启动 Tomcat, 使用 jps -l 命令 (Linux 也可以使用 ps -ef | grep java), 查看本机上所有正在运行的 Java 程序

在这里插入图片描述
可以看到, Tomcat 的主启动类是 org.apache.catalina.startup.Bootstrap

初始化各个组件

先来到 Bootstrap 类, 查看 Bootstrap 的 main 方法

synchronized (daemonLock) {
   
    if (daemon == null) {
   
        Bootstrap bootstrap = new Bootstrap();
        try {
   
            // 初始化类加载器, 并创建 Catalina 对象
            bootstrap.init();
        }
        ....
        daemon = bootstrap;
    }
    else {
   
        Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    }
}

try {
   
    String command = "start";
    ....
    // 默认进入此行代码
    else if (command.equals("start")) {
   
        daemon.setAwait(true);
        // 利用反射调用 Catalina 的 load 方法, 加载各个组件
        daemon.load(args);
        // 启动各个组件
        daemon.start();
        if (null == daemon.getServer()) {
   
            System.exit(1);
        }
    }......
}

Catalina

查看 load 方法

// 创建一个解析 xml 文件的对象
Digester digester = createStartDigester();
try {
   
    try {
   
        // 拿到 server.xml 配置文件
        file = configFile();
        .....
    }
    try {
   
        ...
        // 完成对 server.xml 配置文件的解析
        // 并创建了默认的组件对象 : StandardServer, StandardService
        // StandardEngine, StandardHost, Connector, Executor, Mapper
        // 并为 Server 添加了六个监听器, 为 Engine 添加监听器 : EngineConfig
        // 为 Host 添加监听器 : HostConfig
        digester.parse(inputSource);
    }
    try {
   
        // 初始化 Server 组件
        getServer().init();
    }
}

接下来初始化各个组件, 其中 StandardServer, StandardService, StandardEngine, Connector, 都继承自 LifecycleBase 抽象类, 这里使用了 模板设计模式, 将公共代码抽取出来放到他们的公共父类中

public final synchronized void init() throws LifecycleException {
   
    if (!state.equals(LifecycleState.NEW)) {
   
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }
    try {
   
        // 标记组件生命周期的状态
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        // 初始化各个组件 Server -> Service -> Engine -> MapperListener -> Connector 
        // 在启动 Container 组件的时候又会初始化 Host, Context, Wrapper, Pipeline, Valve 组件
        initInternal();
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    }
    ....
}

监听器

Server 默认存在六个生命周期监听器 (这些监听器对应 server.xml 配置文件中配置的监听器), 监听 Server 在生命周期中发生的事件, 并进行相应处理

  • NameContextListener

    用于初始化和填充与每个 Context 和 Server 关联的的 JNDI 服务

  • VersionLoggerListener

    用于以日志形式输出服务器 、操作系统、JVM的版本信息

  • AprLifecycleListener

    用于加载 (服务器启动) 和 销毁 (服务器停止) APR。 如果找不到 APR 库, 则会输出日志, 并不影响Tomcat启动

  • JreMemoryLeakPreventionListener

    用于避免 JRE 内存泄漏问题

  • GlobalResourcesLifecycleListener

    用户加载 (服务器启动) 和 销毁 (服务器停止) 全局命名服务

  • ThreadLocalLeakPreventionListener

    用于在 Context 停止时重建 Executor 池中的线程, 以避免 ThreadLocal 相关的内存泄漏

Lifecycle

由于所有的组件均存在初始化、启动、停止等生命周期方法,拥有生命周期管理的特性, 所以 Tomcat 在设计的时候, 基于生命周期管理抽象成了一个接口 Lifecycle ,而组件 Server、Service、Container、Executor、Connector 组件 , 都实现了 Lifecycle 接口,从而具有了以下生命周期中的核心方法:

  • init() :初始化组件
  • start() :启动组件
  • stop() :停止组件
  • destroy() :销毁组件

在 Lifecycle 的 Javadoc 文档中, 有这样的一段注释

在这里插入图片描述

描述了各个组件执行完对应的方法后, 应处于哪种生命周期状态

各组件的默认实现

上面提到的 Server、Service、Engine、Host、Context 都是接口, 的默认实现类都是加上 Standard 前缀的, 比如 StandardServer, StandardService …

在这里插入图片描述

ProtocolHandler : Coyote 协议接口,通过封装 Endpoint 和 Processor , 实现针对具体协议的处理功能。Tomcat按照协议和 IO 提供了6个实现类。

AJP协议:
  • AjpNioProtocol :采用 NIO 的 IO 模型。
  • AjpNio2Protocol:采用 NIO2 的IO模型。
  • AjpAprProtocol :采用 APR 的 IO 模型,需要依赖于 APR 库。
HTTP协议:
    <
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值