Tomcat源码分析之—组件启动实现分析

Tomcat由多个组件组成,那么Tomcat是怎么对他们的生命周期进行管理的么,这里将从Tomcat源码去分析其生命周期的实现;

Bootstrape类为Tomcat的入口,所有的组件够通过实现Lifecycle接口来管理生命周期,Tomcat启动的时候只需调用Server容器的start(),然后父容器依序启动他所包含的子容器,关闭也是如此。

通过阅读源码可知一个Server里包含一个或多个Service,一个Service里包含一个Container,一个或多个Connector、Container又包含了Engine、Host、Context、Wrapper四个容器;

?

Tomcat的组件启动顺序为:

StandardServer.start()——》StandardServer.startInternal() ——》StandardService().start()——StandardService.startInternal() ——>》StandardEngine().start() ——》StandardEngine.startInternal()—》StandardEngine中启动其他组件,组件关闭也是如此;

现在我们通过Demo简单模拟Tomcat的启动

模拟Demo UML类图

模拟Demo时序图

主要代码段如下:

Catalina类:

package co.solinx.Pattern.Observer;

/**
 * Created by LX on 2014/11/26.
 */
public class Catalina {

    public static void main(String[] args) {

        //Tomcat为多个组件组成的server为最外围最大的一个
        StandardServer server = new StandardServer();        //为server添加监听器
        server.addLifecycleListener(new ContextConfig());
        //添加一个service
        StandardService service = new StandardService();
        server.AddService(service);       //为service添加监听器
        service.addLifecycleListener(new ContextConfig());
        //添加一个engine
        StandardEngine standardEngine = new StandardEngine();        //为engine添加监听器
        standardEngine.addLifecycleListener(new EngineConfig());
        StandardHost standardHost = new StandardHost("localhost");
//        StandardHost testHost = new StandardHost("test");
//        standardHost.addLifecycleListener(new EngineConfig());
        standardEngine.addChild("localhost", standardHost);
//        standardEngine.addChild("test", testHost);
        //往service添加engine容器
        service.setContainer(standardEngine);
        try {
            server.start();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }
    }

}

StandardServer类

package co.solinx.Pattern.Observer;

/**
 * Created by LX on 2014/11/26.
 */
public class StandardServer extends LifecycleBase implements Context {
    Service services[] = new Service[0];
    @Override
    protected void startInternal() throws LifecycleException {

        for (int i = 0; i < services.length; i++) {
            services[i].start();
        }

        System.out.println("StandardServer start");
    }
    public void AddService(Service service) {
        Service result[] = new Service[services.length + 1];
        System.arraycopy(services, 0, result, 0, services.length);
        result[services.length] = service;
        services = result;
    }
}

StandardService类:

package co.solinx.Pattern.Observer;

/**
 * Created by LX on 2014/11/26.
 */
public class StandardService extends LifecycleBase implements Service, Context {

    protected ContainerBase container = null;

    @Override
    protected void startInternal() throws LifecycleException {

        container.start();
        System.out.println("StandardService start");
    }

    public void setContainer(ContainerBase container) {
        this.container = container;
    }

}

StandardEngine类:

package co.solinx.Pattern.Observer;

/**
 * Created by LX on 2014/11/26.
 */
public class StandardEngine extends ContainerBase {
    @Override
    protected void startInternal() throws LifecycleException {
        super.startInternal();
        System.out.println("StandardEngine start");
    }

    protected void addChild(String key, Container container) {
        super.addChild(key, container);
    }
}

LifecycleSupport类:

package co.solinx.Pattern.Observer;

/**
 * Created by LX on 2014/11/26.
 * 代理了具体监听者
 */
public class LifecycleSupport {
    public LifecycleSupport(Lifecycle lifecycle) {
        super();
        this.lifecycle = lifecycle;
    }
    private Lifecycle lifecycle = null;
    private LifecycleListener listeners[] = new LifecycleListener[0];
    private final Object listenersLock = new Object(); // Lock object for changes to listeners
    public void addLifecycleListener(LifecycleListener listener) {
        synchronized (listenersLock) {
            LifecycleListener results[] =
                    new LifecycleListener[listeners.length + 1];
            for (int i = 0; i < listeners.length; i++)
                results[i] = listeners[i];
            results[listeners.length] = listener;
            listeners = results;
        }
    }
    public LifecycleListener[] findLifecycleListeners() {
        return listeners;
    }
    public void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
        LifecycleListener interested[] = listeners;
        for (int i = 0; i < interested.length; i++)
            interested[i].lifecycleEvent(event);
    }
    public void removeLifecycleListener(LifecycleListener listener) {
        synchronized (listenersLock) {
            int n = -1;
            for (int i = 0; i < listeners.length; i++) {
                if (listeners[i] == listener) {
                    n = i;
                    break;
                }
            }
            if (n < 0)
                return;
            LifecycleListener results[] =
                    new LifecycleListener[listeners.length - 1];
            int j = 0;
            for (int i = 0; i < listeners.length; i++) {
                if (i != n)
                    results[j++] = listeners[i];
            }
            listeners = results;
        }
    }
}

 

模拟程序运行结果:

文章首发地址:Solinx

http://www.solinx.co/archives/86

时间: 2024-12-15 02:00:52

Tomcat源码分析之—组件启动实现分析的相关文章

简单看,tomcat源码(一)启动与监听

tomcat 作为知名的web容器,很棒! 本文简单了从其应用命令开始拆解,让我们对他有清晰的了解,揭开神秘的面纱!(冗长的代码流水线,给你一目了然) 话分两头: 1. tomcat是如何启动的? 2. tomcat是如何接收请求的? x. 应用程序是怎样接入tomcat的? 从何处开始? /etc/init.d/tomcat8 start # 简单的 tomcat8 脚本封装 . "$_"/usr/java/jdk1.8.0_101/bin/java org.apache.catal

Tomcat源码分析之—具体启动流程分析

从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息.Catalina.base信息,在initClassLoaders方法中初始化类加载器,然后通过反射初始化org.apache.catalina.startup.Catalina作为catalina守护进程: 一.load Bootstrap中load流程: 反射调用Catalina的load方法

Tomcat 源码分析(一)——启动与生命周期组件

写在前面的话:读Tomcat源码也有段时间了,大领悟谈不上.一些小心得记录下来,供大家参考相护学习. 一.启动流程 Tomcat启动首先需要熟悉的是它的启动流程.和初学者第一天开始写Hello World一样,Tomcat的启动也依赖main方法. 1 /* 2 * org.apache.catalina.startup.Bootstrap 3 */ 4 if (daemon == null) { 5 Bootstrap bootstrap = new Bootstrap(); // 实例对象

TOMCAT源码分析(启动框架)

建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, 是不那么容易掌握TOMCAT的框架的. 所以得实践.实践.再实践. 建议下载一份TOMCAT的源码, 调试通过, 然后单步跟踪其启动过程. 如果有不明白的地方, 再来查阅本文, 看是否能得到帮助. 我相信这样效果以及学习速度都会好很多! 1. Tomcat的整体框架结构 Tomcat的基本框架, 分为4个层次. Top Level Elements: Server Service Connector HTTP AJP Conta

Tomcat源码分析——启动与停止服务

前言 熟悉Tomcat的工程师们,肯定都知道Tomcat是如何启动与停止的.对于startup.sh.startup.bat.shutdown.sh.shutdown.bat等脚本或者批处理命令,大家一定知道改如何使用它,但是它们究竟是如何实现的,尤其是shutdown.sh脚本(或者shutdown.bat)究竟是如何和Tomcat进程通信的呢?本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程. 由于在生产环境中,Tomcat一般部署在Linux系统下,所以本文将以startup.s

Tomcat 源码分析(转)

Tomcat源码分析(一)--服务启动 1. Tomcat主要有两个组件,连接器和容器,所谓连接器就是一个http请求过来了,连接器负责接收这个请求,然后转发给容器.容器即servlet容器,容器有很多层,分别是Engine,     Host,Context,Wrapper.最大的容器Engine,代表一个servlet引擎,接下来是Host,代表一个虚拟机,然后是Context,代表一个应用,Wrapper对应一个servlet.从连接器     传过来连接后,容器便会顺序经过上面的容器,最

Tomcat源码分析——Session管理分析(上)

前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对于使用Tomcat作为Web容器的大部分开发人员而言,Tomcat是如何实现Session标记用户和管理Session信息的呢? 概要 Session Tomcat内部定义了Session和HttpSession这两个会话相关的接口,其类继承体系如图1所示. 图1 Session类继承体系 图1中额

Tomcat源码分析

前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, 是不那么容易掌握TOMCAT的框架的. 所以得实践.实践.再实践. 建议下载一份TOMCAT的源码, 调试通过, 然后单步跟踪其启动过程. 如果有不明白的地方, 再来查阅本文, 看是否能得到帮助. 我相信这样效果以及学习速度都会好很多! 1. Tomcat的整体框架结构 Tomcat的基本框架,

Tomcat源码分析——请求原理分析(中)

前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原理分析(上)>一文中的相关知识以及HTTP协议和TCP协议的一些内容.本文重点讲解Tomcat7.0在准备好接受请求后,请求过程的原理分析. 请求处理架构 在正式开始之前,我们先来看看图1中的Tomcat请求处理架构. 图1 Tomcat请求处理架构 图1列出了Tomcat请求处理架构中的主要组件,这里