Tomcat生命周期

java事件机制包括三个部分:事件、事件监听器、事件源。

事件:一般继承自java.util.EventObject类,封装了事件源对象,事件类型及跟事件相关的信息。

事件监听器:实现java.util.EventListener接口,注册在事件源上,当事件源的属性或状态改变时,取得相应的监听器调用其内部的回调方法。

事件源:事件发生的地方,由于事件源的某项属性或状态发生了改变(比如BUTTON被单击、TEXTBOX的值发生改变等等)导致某项事件发生。

//事件监听器好比一个间谍,要获取情报需要把她放到敌方阵营,当敌方有任何行动,就放一只鸽子通知友军或者秘密做一些事情

在之前的 Tomcat 整体架构中可以看到 Tomcat 包含多个很多个组件 , 今天我们来看看, Tomcat 是如何管理这些组件的生命周期的。

我们知道,组件与组件之间,必须建立起相互的关系,才能做到同时启动与停止。 Tomcat 内部,使用一个观察者模式来组织这些组件之间的关系。

我们来看看, Tomcat 启动时,它会做哪些处理……

日志:

Html代码  

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

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

Java代码  

  1. StandardService --> StandardEngine-->Http11Protocol-->JkMain-->Catalina

OK, 我们来看看在 Tomcat 内部的,他是如何做的

首先, Tomcat内部的生命周期的相关定义都在接口 Lifecycle 中,

Java代码  

  1. package org.apache.catalina;
  2. public interface Lifecycle {
  3. public static final String INIT_EVENT = "init";
  4. public static final String START_EVENT = "start";
  5. public static final String BEFORE_START_EVENT = "before_start";
  6. public static final String AFTER_START_EVENT = "after_start";
  7. public static final String STOP_EVENT = "stop";
  8. public static final String BEFORE_STOP_EVENT = "before_stop";
  9. public static final String AFTER_STOP_EVENT = "after_stop";
  10. public static final String DESTROY_EVENT = "destroy";
  11. public static final String PERIODIC_EVENT = "periodic";
  12. public void addLifecycleListener(LifecycleListener listener);
  13. public LifecycleListener[] findLifecycleListeners();
  14. public void removeLifecycleListener(LifecycleListener listener);
  15. public void start() throws LifecycleException;
  16. public void stop() throws LifecycleException;
  17. }

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

Java代码  

  1. package org.apache.catalina;
  2. import java.util.EventObject;
  3. public final class LifecycleEvent
  4. extends EventObject {
  5. // ----------------------------------------------------------- Constructors
  6. public LifecycleEvent(Lifecycle lifecycle, String type) {
  7. this(lifecycle, type, null);
  8. }
  9. public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
  10. super(lifecycle);
  11. this.lifecycle = lifecycle;
  12. this.type = type;
  13. this.data = data;
  14. }
  15. private Object data = null;
  16. private Lifecycle lifecycle = null;
  17. private String type = null;
  18. public Object getData() {
  19. return (this.data);
  20. }
  21. public Lifecycle getLifecycle() {
  22. return (this.lifecycle);
  23. }
  24. public String getType() {
  25. return (this.type);
  26. }
  27. }

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

Java代码  

  1. package org.apache.catalina;
  2. public interface LifecycleListener {
  3. public void lifecycleEvent(LifecycleEvent event);//这里间谍秘密做一些事情
  4. }

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

Java代码  

  1. package org.apache.catalina.util;
  2. import org.apache.catalina.Lifecycle;
  3. import org.apache.catalina.LifecycleEvent;
  4. import org.apache.catalina.LifecycleListener;
  5. public final class LifecycleSupport {
  6. public LifecycleSupport(Lifecycle lifecycle) {
  7. super();
  8. this.lifecycle = lifecycle;
  9. }
  10. private Lifecycle lifecycle = null;
  11. private LifecycleListener listeners[] = new LifecycleListener[0];
  12. private final Object listenersLock = new Object(); // Lock object for changes to listeners
  13. public void addLifecycleListener(LifecycleListener listener) {
  14. synchronized (listenersLock) {
  15. LifecycleListener results[] =
  16. new LifecycleListener[listeners.length + 1];
  17. for (int i = 0; i < listeners.length; i++)
  18. results[i] = listeners[i];
  19. results[listeners.length] = listener;
  20. listeners = results;
  21. }
  22. }
  23. public LifecycleListener[] findLifecycleListeners() {
  24. return listeners;
  25. }
  26. //这里就是调用各个监听器的方法
  27. public void fireLifecycleEvent(String type, Object data) {
  28. LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
  29. LifecycleListener interested[] = listeners;
  30. for (int i = 0; i < interested.length; i++)
  31. interested[i].lifecycleEvent(event);
  32. }
  33. public void removeLifecycleListener(LifecycleListener listener) {
  34. synchronized (listenersLock) {
  35. int n = -1;
  36. for (int i = 0; i < listeners.length; i++) {
  37. if (listeners[i] == listener) {
  38. n = i;
  39. break;
  40. }
  41. }
  42. if (n < 0)
  43. return;
  44. LifecycleListener results[] =
  45. new LifecycleListener[listeners.length - 1];
  46. int j = 0;
  47. for (int i = 0; i < listeners.length; i++) {
  48. if (i != n)
  49. results[j++] = listeners[i];
  50. }
  51. listeners = results;
  52. }
  53. }
  54. }

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

在service真正启动时,他首先会触发一些启动前的事件,

然后启动它自己

接着,它会启动它关联的容器对象,

然后,将所有它的子组件—既连接器 全部都启动 ,下面是详细的代码/

Java代码  

  1. public class StandardService
  2. implements Lifecycle, Service, MBeanRegistration
  3. {
  4. .............
  5. /**
  6. * The lifecycle event support for this component.
  7. */
  8. private LifecycleSupport lifecycle = new LifecycleSupport(this);//this就是事件源
  9. .............
  10. /**
  11. * The set of Connectors associated with this Service.
  12. 关联到这个Service的连接器对象.
  13. */
  14. protected Connector connectors[] = new Connector[0];
  15. public void start() throws LifecycleException {
  16. // Validate and update our current component state
  17. if (log.isInfoEnabled() && started) {
  18. log.info(sm.getString("standardService.start.started"));
  19. }
  20. if( ! initialized )
  21. init();
  22. // 触发启动之前的事件
  23. lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);//BEFORE_START_EVENT事件类型,监听器一般需要这个两个东西,事件源和事件类型。fire就是运行监听器的方法。
  24. if(log.isInfoEnabled())
  25. log.info(sm.getString("standardService.start.name", this.name));
  26. lifecycle.fireLifecycleEvent(START_EVENT, null);  <<<<(1)
  27. started = true;
  28. // Start our defined Container first 首先启动关联的容器
  29. if (container != null) {
  30. synchronized (container) {
  31. if (container instanceof Lifecycle) {
  32. ((Lifecycle) container).start();
  33. }
  34. }
  35. }
  36. synchronized (executors) {
  37. for ( int i=0; i<executors.size(); i++ ) {
  38. executors.get(i).start();
  39. }
  40. }
  41. // Start our defined Connectors second 再启动关联的连接器
  42. synchronized (connectors) {
  43. for (int i = 0; i < connectors.length; i++) {
  44. if (connectors[i] instanceof Lifecycle)
  45. ((Lifecycle) connectors[i]).start();
  46. }
  47. }
  48. // Notify our interested LifecycleListeners
  49. lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
  50. }

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

Java代码  

  1. public void fireLifecycleEvent(String type, Object data) {
  2. LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
  3. LifecycleListener interested[] = listeners;
  4. for (int i = 0; i < interested.length; i++)
  5. interested[i].lifecycleEvent(event);
  6. }

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

Java代码  

  1. package org.apache.catalina.mbeans;
  2. public class ServerLifecycleListener
  3. implements ContainerListener, LifecycleListener, PropertyChangeListener {
  4. public void lifecycleEvent(LifecycleEvent event) {
  5. Lifecycle lifecycle = event.getLifecycle();
  6. if (Lifecycle.START_EVENT.equals(event.getType())) {
  7. if (lifecycle instanceof Server) {
  8. createMBeans();
  9. }
  10. // We are embedded.
  11. if( lifecycle instanceof Service ) {
  12. try {
  13. //Service启动时,触发的事件
  14. MBeanFactory factory = new MBeanFactory();
  15. createMBeans(factory);
  16. createMBeans((Service)lifecycle);
  17. } catch( Exception ex ) {
  18. log.error("Create mbean factory");
  19. }
  20. }
  21. /*
  22. // Ignore events from StandardContext objects to avoid
  23. // reregistering the context
  24. if (lifecycle instanceof StandardContext)
  25. return;
  26. createMBeans();
  27. */
  28. } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
  29. try {
  30. if (lifecycle instanceof Server) {
  31. destroyMBeans((Server)lifecycle);
  32. }
  33. if (lifecycle instanceof Service) {
  34. destroyMBeans((Service)lifecycle);
  35. }
  36. } catch (MBeanException t) {
  37. Exception e = t.getTargetException();
  38. if (e == null) {
  39. e = t;
  40. }
  41. log.error("destroyMBeans: MBeanException", e);
  42. } catch (Throwable t) {
  43. log.error("destroyMBeans: Throwable", t);
  44. }
  45. // FIXME: RMI adaptor should be stopped; however, this is
  46. // undocumented in MX4J, and reports exist in the MX4J bug DB that
  47. // this doesn‘t work
  48. }
  49. if ((Context.RELOAD_EVENT.equals(event.getType()))
  50. || (Lifecycle.START_EVENT.equals(event.getType()))) {
  51. // Give context a new handle to the MBean server if the
  52. // context has been reloaded since reloading causes the
  53. // context to lose its previous handle to the server
  54. if (lifecycle instanceof StandardContext) {
  55. // If the context is privileged, give a reference to it
  56. // in a servlet context attribute
  57. StandardContext context = (StandardContext)lifecycle;
  58. if (context.getPrivileged()) {
  59. context.getServletContext().setAttribute
  60. (Globals.MBEAN_REGISTRY_ATTR,
  61. MBeanUtils.createRegistry());
  62. context.getServletContext().setAttribute
  63. (Globals.MBEAN_SERVER_ATTR,
  64. MBeanUtils.createServer());
  65. }
  66. }
  67. }
  68. }
  69. }

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

推荐书籍:how tomcat works.

时间: 2024-10-09 12:21:46

Tomcat生命周期的相关文章

tomcat生命周期的管理——生命周期统一接口Lifecycle

我们知道Tomcat的架构设计是清晰的.模块化的,其拥有很多组件,假如我们要启动Tomcat,可以一个一个启动组件,但这样启动有很多缺点,不仅麻烦,而且容易漏了组件启动,还会对后面动态组件扩展带来麻烦.难不成真要我们一个一个启动吗?其实未必,Tomcat的设计者提供了一个解决方案:用Lifecycle管理启动.停止.关闭. 从第一节的架构图可以看到各个核心组件有包含与被包含的关系,例如Server<-Service<-Container和Connector,最大的是Server,往下一层层包含

深入浅出Tomcat/3 - Tomcat生命周期

在上面的部分,其实我们已经接触到Tomcat的生命周期了,接下来我们将仔细讨论和学习Tomcat的生命周期的具体实现. LifeCycle接口 这个LifeCycle接口上面在讲解Server和Service时其实已经有所接触.Tomcat通过org.apache.catalina.LifeCycle接口统一接管Tomcat的生命周期,所有继承自它的组件(即Component)都需要实现这个接口. 我们先俯视看一看LifeCycle接口的定义. 根据上图,我们清晰看到上图包含了4个生命周期的方法

Tomcat7.0源码分析——生命周期管理

前言 从server.xml文件解析出来的各个对象都是容器,比如:Server.Service.Connector等.这些容器都具有新建.初始化完成.启动.停止.失败.销毁等状态.tomcat的实现提供了对这些容器的生命周期管理,本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程. Tomcat生命周期类接口设计 我们先阅读图1,从中了解Tomcat涉及生命周期管理的主要类. 图1 Tomcat生命周期类接口设计 这里对图1中涉及的主要类作个简单介绍: Lifecycle:定义了容器生命

tomcat系列分析之生命周期管理初始化动作

tomcat中有很多组件,要对这些组件进行生命周期的管理非常困难,tomcat中采用的是抽象出一个生命周期管理接口,然后所有的组件都实现该接口,当父组件启动时,同事负责将子组件启动起来,从而完成整tomcat的初始.启动.结束等动作. 来看下tomcat启动的过程,首先构造Bootstrap类,调用其中的init方法,完成类加载器的初始化,方便后面加载类使用,然后调用其中的load方法,实际上tomcat真正的启动动作是由Catalina类完成的.而这其中在BootStrap中调用Catalin

javaEE:day2-servlet生命周期、提交解决中文乱码、tomcat加载jar包或类文件的顺序

servlet生命周期 生命周期简介: servlet在服务器第一次被请求的时候new出来,并初始化(即init())再调用service方法.这个实在服务器中new出来,然后用HashMap加的,与客户端无关.客户端之后访问只调用这个servlet的service方法. 具体分为4步: 1 构造方法 :服务器在被客户端第一次请求的时候运行 仅在服务器中运行一次 2 init方法:客户端第一次访问服务器的时候在服务器中进行初始化 仅一次.并且可以通过config参数在 web.xml中通过(ke

servlet图解。1。。tomcat处理请求过程、servlet的生命周期

Tomcat的组成部分 Tomcat容器的处理请求过程 servlet的生命周期 HttpServletRequest HttpServletResponse

Tomcat 8(九)解读Tomcat组件的生命周期(Lifecycle)

Tomcat 8(七)解读Bootstrap介绍过.运行startup.bat.将引发Tomcat一连串组件的启动.事实上这一连串启动是通过组件的生命周期(Lifecycle)实现的 今天来看看Lifecycle设计.解读Lifecycle.涉及到例如以下几个类 Lifecycle.LifecycleState.LifecycleEvent.LifecycleListener(位于org.apache.catalina) LifecycleBase.LifecycleSupport.Lifecy

【转】Tomcat组件生命周期管理

Tomcat组件生命周期管理 Tomcat中Server,Service,Connector,Engine,Host,Context,它们都实现了org.apache.catalina.Lifecycle接口,而org.apache.catalina.util.LifecycleBase采用了模板方法模式来对所有支持生命周期管理的组件的生命周期各个阶段进行了总体管理,每个需要生命周期管理的组件只需要继承这个基类,然后覆盖对应的钩子方法即可完成相应的生命周期阶段性的管理工作. 下面我们首先来看看o

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

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