【百度面试官】Tomcat的源码剖析, 启动过程你会吗?

点关注,不迷路!如果本文对你有帮助的话不要忘记点赞支持哦!

好了,今天我们继续分析 tomcat 源码, 这是第六篇了, 上一篇我们一边 debug 一边研究了 tomcat 的类加载体系, 我觉得效果还不错, 楼主感觉对 tomcat 的类加载体系的理解又加深了一点. 所以, 我们今天还是按照之前的方式来继续看源码, 一边 debug, 一边看, 今天我们分析的是tomcat 中2个非常重要的组件-------生命周期和容器. tomcat 庞大的架构, 他是如何管理每个对象的呢?

基于JMX Tomcat会为每个组件进行注册过程,通过Registry管理起来,而Registry是基于JMX来实现的,因此在看组件的init和start过程实际上就是初始化MBean和触发MBean的start方法,会大量看到形如: Registry.getRegistry(null, null).invoke(mbeans, "init", false); Registry.getRegistry(null, null).invoke(mbeans, "start", false); 这样的代码,这实际上就是通过JMX管理各种组件的行为和生命期。

当时大家可能还不是很理解这句话, 觉得这是在扯淡, 听不懂. 好吧, 今天我们就用代码说话, 看看 JMX 到底怎么管理 tomcat 的 组件.

1. 什么是 JMX?

我们之前说过:

JMX 即 Java Management Extensions(JMX 规范), 是用来对 tomcat 进行管理的. tomcat 中的实现是 commons modeler 库, Catalina 使用这个库来编写托管 Bean 的工作. 托管 Bean 就是用来管理 Catalina 中其他对象的 Bean.

简单来说: 就是一个可以为Java应用程序或系统植入远程管理功能的框架。

既然是框架, 肯定要有架构图:

 

这里对上图中三个分层进行介绍:

  • Probe Level:负责资源的检测(获取信息),包含MBeans,通常也叫做Instrumentation Level。MX管理构件(MBean)分为四种形式,分别是标准管理构件(Standard MBean)、动态管理构件(Dynamic MBean)、开放管理构件(Open Mbean)和模型管理构件(Model MBean)。

  • Agent Level:即MBeanServer,是JMX的核心,负责连接Mbeans和应用程序。

  • Remote Management Level:通过connectors和adaptors来远程操作MBeanServer,常用的控制台,例如JConsole、VisualVM(等会我们就要用这个)等。

2. 我们看看生命周期组件接口是如何设计的:

这是一张 IDEA 生成的简单的 StandardHost(Host 容器的标准实现) 的 UML类图, 基本上, tomcat 的容器类都是这样的继承结构.

因此我们就可以直接看下面这张图:

 

这里对上图中涉及的主要类作个简单介绍:

  1. Lifecycle:定义了容器生命周期、容器状态转换及容器状态迁移事件的监听器注册和移除等主要接口;

  2. LifecycleBase:作为Lifecycle接口的抽象实现类,运用抽象模板模式将所有容器的生命周期及状态转换衔接起来,此外还提供了生成LifecycleEvent事件的接口;

  3. LifecycleSupport:提供有关LifecycleEvent事件的监听器注册、移除,并且使用经典的监听器模式,实现事件生成后触达监听器的实现;

  4. MBeanRegistration:Java JMX框架提供的注册MBean的接口,引入此接口是为了便于使用JMX提供的管理功能;

  5. LifecycleMBeanBase:Tomcat提供的对MBeanRegistration的抽象实现类,运用抽象模板模式将所有容器统一注册到JMX;

  6. 此外,ContainerBase、StandardServer、StandardService、WebappLoader、Connector、StandardContext、StandardEngine、StandardHost、StandardWrapper等容器都继承了LifecycleMBeanBase,因此这些容器都具有了同样的生命周期并可以通过JMX进行管理。

3. 再看看我们的容器结构

我们之前说, 如果从宏观上讲容器, 画画图, 讲讲就好了, 就可以在脑海里形成一个映象, 今天, 我们要好好的讲讲容器, 从代码层面去理解他们. 这样一来, 也顺便把我们的容器组件也讲了, 等于又讲了生命周期组件, 还有容器组件. 一举两得. 哈哈哈. 好吧, 不扯了, 回来, 我们继续讲容器. 还是先来一张图吧:

从上图中我们可以看到: StandardServer、StandardService、Connector、StandardContext这些容器,彼此之间都有父子关系,每个容器都可能包含零个或者多个子容器,这些子容器可能存在不同类型或者相同类型的多个. 所以他们都包含的关系, 如果让你来设计这些容器的生命周期, 你会用什么设计模式呢?

4. 容器初始化, 开始 Debug

首先我们启动 main 方法:

 


    public static void main(String args[]) {
        try {
            // 命令
            String command = "start";
            // 如果命令行中输入了参数
            if (args.length > 0) {
                // 命令 = 最后一个命令
                command = args[args.length - 1];
            }
            // 如果命令是启动
            if (command.equals("startd")) {
                args[args.length - 1] = "start";
                daemon.load(args);
                daemon.start();
            }
            // 如果命令是停止了
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值