`
gogole_09
  • 浏览: 201935 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Tomcat生命周期管理

阅读更多

在之前的 Tomcat 整体架构中可以看到 Tomcat 包含多个很多个组件 , 今天我们来看看, Tomcat 是如何管理这些组件的生命周期的。
我们知道,组件与组件之间,必须建立起相互的关系,才能做到同时启动与停止。 Tomcat 内部,使用一个观察者模式来组织这些组件之间的关系。
我们来看看, Tomcat 启动时,它会做哪些处理……
日志:

……

2010-6-19 15:41:18 org.apache.catalina.core.StandardService start
信息 : Starting service Catalina
2010-6-19 15:41:18 org.apache.catalina.core.StandardEngine start
信息 : Starting Servlet Engine: Apache Tomcat/6.0.18
…
2010-6-19 15:41:19 org.apache.coyote.http11.Http11Protocol start
信息 : Starting Coyote HTTP/1.1 on http-8080
2010-6-19 15:41:19 org.apache.jk.common.ChannelSocket init
信息 : JK: ajp13 listening on /0.0.0.0:8009
2010-6-19 15:41:19 org.apache.jk.server.JkMain start
信息 : Jk running ID=0 time=0/182 config=null
2010-6-19 15:41:19 org.apache.catalina.startup.Catalina start
信息 : Server startup in 1706 ms
 



我们看到,它的启动顺序:

StandardService --> StandardEngine-->Http11Protocol-->JkMain-->Catalina
 


OK, 我们来看看在 Tomcat 内部的,他是如何做的
首先, Tomcat内部的生命周期的相关定义都在接口 Lifecycle 中,

 

package org.apache.catalina;


public interface Lifecycle {

    public static final String INIT_EVENT = "init";

    public static final String START_EVENT = "start";

    public static final String BEFORE_START_EVENT = "before_start";

    public static final String AFTER_START_EVENT = "after_start";
    public static final String STOP_EVENT = "stop";
    public static final String BEFORE_STOP_EVENT = "before_stop";
    public static final String AFTER_STOP_EVENT = "after_stop";
    public static final String DESTROY_EVENT = "destroy";
    public static final String PERIODIC_EVENT = "periodic";
    public void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
}

 

另外生命周期的相关事件,定义在 LifecycleEvent 类中

 

 

 

package org.apache.catalina;



import java.util.EventObject;


public final class LifecycleEvent

    extends EventObject {
    // ----------------------------------------------------------- Constructors
    public LifecycleEvent(Lifecycle lifecycle, String type) {
        this(lifecycle, type, null);
    }

    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
        super(lifecycle);
        this.lifecycle = lifecycle;
        this.type = type;
        this.data = data;
    }

    private Object data = null;

    private Lifecycle lifecycle = null;

    private String type = null;

    public Object getData() {
        return (this.data);
    }

    public Lifecycle getLifecycle() {
        return (this.lifecycle);
    }

    public String getType() {
        return (this.type);
    }

}

 

 

关于事件的监听,在接口LifecycleListener 中有定义

 

 

package org.apache.catalina;

public interface LifecycleListener {
    public void lifecycleEvent(LifecycleEvent event);
}

 

 另外,这里还需要介绍一个特别的类:LifecycleSupport, 用于触发生命周期的相关事件.

 

package org.apache.catalina.util;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public final 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;
        }
    }
}

 

 

下面,我们来看看 StandardService 类的启动方法, 看它是如何启动的

   在service真正启动时,他首先会触发一些启动前的事件,
    然后启动它自己
    接着,它会启动它关联的容器对象,
    然后,将所有它的子组件—既连接器 全部都启动 ,下面是详细的代码/

public class StandardService
        implements Lifecycle, Service, MBeanRegistration 
 {
   .............
    /**
     * The lifecycle event support for this component.
     */
    private LifecycleSupport lifecycle = new LifecycleSupport(this);
    .............
    /**
     * The set of Connectors associated with this Service.
       关联到这个Service的连接器对象.
     */
    protected Connector connectors[] = new Connector[0];
    
    public void start() throws LifecycleException {
        // Validate and update our current component state
        if (log.isInfoEnabled() && started) {
            log.info(sm.getString("standardService.start.started"));
        }
        
        if( ! initialized )
            init(); 

        // 触发启动之前的事件
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));

        lifecycle.fireLifecycleEvent(START_EVENT, null);  <<<<(1)
        started = true;
        // Start our defined Container first 首先启动关联的容器
        if (container != null) {
            synchronized (container) {
                if (container instanceof Lifecycle) {
                    ((Lifecycle) container).start();
                }
            }
        }

        synchronized (executors) {
            for ( int i=0; i<executors.size(); i++ ) {
                executors.get(i).start();
            }
        }

        // Start our defined Connectors second 再启动关联的连接器
        synchronized (connectors) {
            for (int i = 0; i < connectors.length; i++) {
                if (connectors[i] instanceof Lifecycle)
                    ((Lifecycle) connectors[i]).start();
            }
        }
        
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

    }

 

代码(1)处,显示出,在Service正式启动之前,它还会出发启动前的事件,我们来看看,这个方法具体做些什么.  调用LifecycleSupport 类的 fireLifecycleEvent(START_EVENT, null);方法

 

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);

    }

 而在内部,Service启动时,这里真正调用的是类 ServerLifecycleListener的方法:

package org.apache.catalina.mbeans;





public class ServerLifecycleListener

    implements ContainerListener, LifecycleListener, PropertyChangeListener {



    public void lifecycleEvent(LifecycleEvent event) {

        Lifecycle lifecycle = event.getLifecycle();
        if (Lifecycle.START_EVENT.equals(event.getType())) {

            if (lifecycle instanceof Server) {
                createMBeans();
            }

            // We are embedded.
            if( lifecycle instanceof Service ) {
                try {
                    //Service启动时,触发的事件
                    MBeanFactory factory = new MBeanFactory();
                    createMBeans(factory);
                    createMBeans((Service)lifecycle);
                } catch( Exception ex ) {
                    log.error("Create mbean factory");
                }
            }

            /*
            // Ignore events from StandardContext objects to avoid
            // reregistering the context
            if (lifecycle instanceof StandardContext)
                return;
            createMBeans();
            */

        } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
            try {
                if (lifecycle instanceof Server) {
                    destroyMBeans((Server)lifecycle);
                }
                if (lifecycle instanceof Service) {
                    destroyMBeans((Service)lifecycle);
                }
            } catch (MBeanException t) {

                Exception e = t.getTargetException();
                if (e == null) {
                    e = t;
                }
                log.error("destroyMBeans: MBeanException", e);

            } catch (Throwable t) {

                log.error("destroyMBeans: Throwable", t);

            }
            // FIXME: RMI adaptor should be stopped; however, this is
            // undocumented in MX4J, and reports exist in the MX4J bug DB that
            // this doesn't work

        }

        if ((Context.RELOAD_EVENT.equals(event.getType()))
            || (Lifecycle.START_EVENT.equals(event.getType()))) {

            // Give context a new handle to the MBean server if the
            // context has been reloaded since reloading causes the
            // context to lose its previous handle to the server
            if (lifecycle instanceof StandardContext) {
                // If the context is privileged, give a reference to it
                // in a servlet context attribute
                StandardContext context = (StandardContext)lifecycle;
                if (context.getPrivileged()) {
                    context.getServletContext().setAttribute
                        (Globals.MBEAN_REGISTRY_ATTR,
                         MBeanUtils.createRegistry());
                    context.getServletContext().setAttribute
                        (Globals.MBEAN_SERVER_ATTR,
                         MBeanUtils.createServer());
                }
            }

        }

    }


}

 

这里简单介绍一下,Tomcat内部的启动流程, 通过观察者模式与监听器模式来作处理, 组件启动方面,在启动上级组件的同时,先启动下一级组件, (当然,在父组件内部,需要包含它所有子组件引用的一个集合).

分享到:
评论
2 楼 mercyblitz 2010-06-21  
个人感觉Tomcat扩张不易,代码风格各异。

1 楼 ilove2009 2010-06-21  
不错         

相关推荐

    tomcat 生命周期,和事件管理—— lifeCycle & event

    NULL 博文链接:https://yjhexy.iteye.com/blog/669427

    类似于Jira的基于JAVA语言写的项目管理软件,可以跟踪任务和bug的进度,实现对任务和bug全生命周期管理。

    使用JAVA语言写的项目管理软件,可以跟踪任务和bug的进度,实现对任务和bug全生命周期管理。 这个项目是很早之前开发的(大约在2008年前后),所以使用的技术是传统的JSP/Servlet+JDBC方式。虽然技术比较老了,但是...

    apache-tomcat-8.5.50-src.zip

    组件的生命周期管理 用Lifecycle管理启动、停止、关闭 Lifecycle接口预览 几个核心方法 Server中的init方法示例 为啥StandardServer没有init方法 LifecycleBase中的init与initInternal方法 为什么这么设计...

    tomcat9.0.0.M26

    在9.x系列的剩余生命周期内完全改变了: - 没有 可以添加以下类的公共接口以便 解决错误和/或添加新功能。没有现有的接口方法 已删除或更改,但可能已弃用。 - 没有 注意:随着Tomcat 9的成熟,以上列表将被添加到...

    eclipse+tomcat+maven

    Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期...

    《深入剖析Tomcat(中文版+英文版)》.rar

    第6章 生命周期 第7章 日志记录器 第8章 载入器 第9章 session管理 第10章 安全性 第11章 standardwrapper 第12章 standardcontext类 第13章 host和engine 第14章 服务器组件和服务组件 第15章 digester库...

    tomcat6、7、8、9, maven3.5

    Tomcat 6.x的用户应该计划在Tomcat 6.x到达生命周期之前进行升级。 Apache Tomcat 5.x 的Apache Tomcat 5.x的是可以从档案下载。 的Apache Tomcat 5.5.X支持相同的Servlet和JSP规范版本的的Apache Tomcat 5.0.x中...

    apache-tomcat-9.0.31-windows-x64.zip

    组件的生命周期方法由容器自动调用。 如何基于tomcat编写服务端动态应用? 基于tomcat编写JSP: JSP (Java Server Page) Java服务端页面生成技术 JSP的本质是一个Servlet类。 如何编写一个JSP? 1&gt;创建...

    tomcat 结构及设计.pptx

    详细的介绍了tomcat的组成结构、生命周期管理以及管道机制。

    JavaWeb程序Tomcat及Servlet配置:实例与组件包-zip压缩包

    Servlet的生命周期由Web容器(如Tomcat)管理,包括加载、初始化、服务、销毁等阶段。 二、组件包 Java EE SDK: Java EE SDK提供了JavaWeb应用程序开发所需的所有API和库。 Tomcat: Tomcat二进制包,包含了Tomcat...

    浅谈Tomcat Session管理分析

    在上文Nginx+Tomcat关于Session的管理中简单介绍了如何使用redis来集中管理session,本文首先将介绍默认的管理器是如何管理Session的生命周期的,然后在此基础上对Redis集中式管理Session进行分析。 Tomcat Manager...

    HowTomcatWorks:《深度剖析Tomcat》原始码及笔记

    第六章生命周期 第七章日志记录器 第八章加载器 第九章会议管理 第十章应用程序 第十一章StandardWrapper 第十二章StandardContext 第十三章主机和引擎 第十四章服务器组件和服务组件 第十五章消化器库 第十六章关闭...

    how-tomcat-works中文版

    讲述Tomcat的工作原理 第1章 一个简单的Web服务器 ...第6章 生命周期(Lifecycle) 第7章 Logger 第8章 Loader 第9章 session管理 第10章 安全性 第11章 StandardWrapper 第12章 StandardContext类 ...

    apache-tomcat-11.0.0-M3-windows-x64

    omcat是一个轻量级应用服务器,是支持运行Servlet/JSP应用程序的容器,运行在jvm上,绑定IP地址并监听...1)管理servlet应用的生命周期 (2)把客户端请求的url映射到对应的servlet (3)与Servlet程序合作处理HTTP请求

    how-tomcat-works

    第6章 生命周期(Lifecycle) 43 6.1 概述 43 6.2 Lifecycle接口 43 6.3 LifecycleEvent类 44 6.4 LifecycleListener接口 44 6.5 LifecycleSupport类 44 6.6 应用程序 45 6.6.1 ex06.pyrmont.core.SimpleContext 45 ...

    管理远程win系统上的tomcat服务.zip

    项目管理系统(PM):对项目全生命周期进行规划、跟踪、控制,确保项目按时、按质、按预算完成。 三、价值与优势 提高效率:自动化工作流程、标准化业务操作,显著减少人工干预,提升工作效率。 优化决策:实时...

    How Tomcat Works: A Guide to Developing Your Own Java Servlet Container

    第6章 生命周期(Lifecycle) 43 6.1 概述 43 6.2 Lifecycle接口 43 6.3 LifecycleEvent类 44 6.4 LifecycleListener接口 44 6.5 LifecycleSupport类 44 6.6 应用程序 45 6.6.1 ex06.pyrmont.core.SimpleContext 45 ...

    java项目之人人乐超市采购管理系统源码(ssm+mysql+jsp).zip

    并且采用了系统生命周期的结构化程序设计方法,从而将整个系统开发各阶段(系统分析、系统设计、系统实施)的基本活动贯穿起来。 所需开发环境: 开发语言:Java JDK版本:JDK1.8 服务器:tomcat7+ 数据库:mysql ...

    java毕业设计之人人乐超市采购管理系统源码(前后端完整源代码).zip

    并且采用了系统生命周期的结构化程序设计方法,从而将整个系统开发各阶段(系统分析、系统设计、系统实施)的基本活动贯穿起来。 所需开发环境: 开发语言:Java JDK版本:JDK1.8 服务器:tomcat7+ 数据库:mysql ...

Global site tag (gtag.js) - Google Analytics