nihaogirl 发表于 2015-8-8 11:11:10

Tomcat生命周期管理与观察者模式

  本文主要结合观察者模式,讲述Tomcat的生命周期管理。Tomcat的生命周期管理机制设计的非常优雅,在Tomcat启动时,只需要启动一个Server组件,就会启动所有的容器及对应的组件,并且触发这些容器的监听者,完成启动过程的设置。可以说是“一键式”启动的。停止过程也是一样。
           本文首先简单介绍Tomcat中容器,组件及监听类的功能。因为Tomcat的生命周期管理应用了观察者模式,所以接下来会分析观察者模式,最后结合观察者模式及Tomcat源代码,详细说明Tomcat的生命周期管理。
  一、几种基本的容器,组件及事件监听类(Listener)
  1.         Tomcat中有四种不同的容器:

[*]
Engine:代表整个Catalina servle引擎
[*]
Host:代表虚拟主机
[*]
Context:代表某个web应用
[*]
Wrapper:代表某个应用中的servlet
           这些容器都扩展了Container接口(译为:容器,这也是为什么一般都称tomcat为容器而不是服务器的原因之一吧~)。更重要的是,这些容器都是父子的关系,Engine位于最顶层,一个Engine包含多个Host,一个Host(虚拟主机)包含多个Context(web应用),一个Context(web 应用)包含多个Wrapper(servlet),Wrapper位于最底层,没有孩子。当父容器启动时,相应的子容器也应该启动,子容器的子容器也启动。如此,只需要启动最顶层的容器,就会启动所有的子容器。
  
  2.         Tomcat的容器中有很多组件,如:

[*]
Logger:负责记录各种事件
[*]
Loader:负责加载类文件,如加载应用程序中的Servlet
[*]
Manager:负责管理session
[*]
Realm: 负责用户验证与授权
[*]
Pipeline:负责完成容器invoke方法的调用,对请求进行处理(责任链模式的经典应用)。
           当tomcat容器启动时,这些组件也要启动,进行初始化。当容器停止时,这些组件也应该停止,进行相应的清理工作。比如管理用户session的Manager组件,在tomcat停止时,会将这些session序列化到sessions.ser文件中(位于%tomcat_home%/work/web appcation/sessions.ser)。下一次启动tomcat时,manager会将这个文件中的session反序列化到内存,将删除sessions.ser文件。这也是为什么重启tomcat时,正在访问网站的用户不用重新登录的原因。
  
  3.         另外,还有一些类,它们并不像容器的基本组件(如Logger, Loader, Manager)一样,为容器的整个生命周期所调用,而仅仅对容器的某几个特定事件感兴趣。如:

[*]
ContextConfig: Context的收听者,在Context(web 应用)启动时,ContextConfig对web应用程序的配置文件web.xml进行分析,为Context生成Wrapper等对象,并与Context关联。在Context停止时,为Context清除这些关联的对象。
[*]
HostConfig: Host的收听者,在Host(虚拟主机)启动时,HostConfig会自动的为Host部署放置在webapps中的web应用程序。在Host停止时,为Host清除这些关联的对象。
[*]
EngineConfig:Engine的收听者,这个对比较简单,仅仅是在Engine启动与停止时做一些简单的记录。
           这些监听类如何监听容器的特定事件呢?如何在特定事件发现时,调用监听类的特定方法以完成某些设置呢?如果理解了观察者模式,便能轻易的理解Tomcat的整个生命周期管理了。
  
  二、观察者模式:
           观察者模式又叫做发布-订阅(Publish/Subscribe)模式、源-监听(Source/Listener)模式。它定义了一种一对多的依赖关系,一个主题,多个观察者,当主题发生变化的时候,会主动的通知观察者,这样观察者便能针对主题发生的变化,执行某些对应的动作。观察者模式的应用非常广泛,如Java AWT事件模型,Servlet的监听器,Spring事件处理机制以及本文所讲述的Tomcat生命周期管理机制等等;应用如此的广泛,以至于Java直接提供API的支持,java.util.Observable和java.util.Observer;
  观察者模式的结构:
  
  
  观察者模式包括以下角色:
  抽象主题(Observable):定义了管理观察者的添加,删除和通知方法。
  抽象观察者(Observer):定义了主题发生变化时,具体观察者必须执行的方法。
  具体主题(Container):对观察者进行管理,并在自身发生变化时,通知观察者。
  具体观察者(ContainerConfig):实现了当主题发生变化时,应该执行的动作。
  
  下面是观察者模式的示例代码:
  package com.scnulh.observer;
  抽象主题:
  
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=%2F**%0A%0A%20*%20%E6%8A%BD%E8%B1%A1%E4%B8%BB%E9%A2%98%0A%0A%20*%2F%0A%0Apublic%20interface%20Observable%20%7B%0A%0A%20%20%20%20%0A%0A%20%20%20%20%2F%2F%E6%B7%BB%E5%8A%A0%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20void%20addObserver(Observer%20observer)%3B%0A%0A%20%20%20%20%2F%2F%E5%88%A0%E9%99%A4%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20void%20deleteObserver(Observer%20observer)%3B%0A%0A%20%20%20%20%2F%2F%E5%9C%A8%E4%BA%8B%E4%BB%B6%E5%8F%91%E7%94%9F%E6%97%B6%EF%BC%8C%E9%80%9A%E7%9F%A5%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20void%20notifyObservers()%3B%0A%0A%7D%0A%0A
[*]/**
[*]
[*] * 抽象主题
[*]
[*] */
[*]
[*]public interface Observable {
[*]
[*]
[*]
[*]    //添加观察者
[*]
[*]    void addObserver(Observer observer);
[*]
[*]    //删除观察者
[*]
[*]    void deleteObserver(Observer observer);
[*]
[*]    //在事件发生时,通知观察者
[*]
[*]    void notifyObservers();
[*]
[*]}
  
  
  
  抽象观察者:



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20com.scnulh.observer%3B%0A%0A%20%0A%0A%2F**%0A%0A%20*%20%E6%8A%BD%E8%B1%A1%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20*%2F%0A%0Apublic%20interface%20Observer%20%7B%0A%0A%20%20%20%20%0A%0A%20%20%20%20%2F**%0A%0A%20%20%20%20%20*%20%E6%9B%B4%E6%96%B0%E6%96%B9%E6%B3%95%EF%BC%8C%E8%A7%82%E5%AF%9F%E8%80%85%E6%A0%B9%E6%8D%AE%E4%BC%A0%E5%85%A5%E7%9A%84%E4%B8%BB%E9%A2%98%E5%AF%B9%E8%B1%A1%E8%8E%B7%E5%8F%96%E4%B8%BB%E9%A2%98%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%0A%0A%20%20%20%20%20*%20%E6%A0%B9%E6%8D%AE%E4%BC%A0%E5%85%A5%E7%9A%84Object%E5%AF%B9%E8%B1%A1%E5%88%A4%E6%96%AD%E5%8F%91%E7%94%9F%E4%BA%86%E4%BD%95%E7%A7%8D%E4%BA%8B%E4%BB%B6%0A%0A%20%20%20%20%20*%20%40param%20observable%0A%0A%20%20%20%20%20*%20%40param%20arg%0A%0A%20%20%20%20%20*%2F%0A%0A%20%20%20%20void%20update(Observable%20observable%2CObject%20arg)%3B%0A%0A%20%0A%0A%7D%0A%0A
[*]package com.scnulh.observer;
[*]
[*]
[*]
[*]/**
[*]
[*] * 抽象观察者
[*]
[*] */
[*]
[*]public interface Observer {
[*]
[*]
[*]
[*]    /**
[*]
[*]   * 更新方法,观察者根据传入的主题对象获取主题的上下文
[*]
[*]   * 根据传入的Object对象判断发生了何种事件
[*]
[*]   * @param observable
[*]
[*]   * @param arg
[*]
[*]   */
[*]
[*]    void update(Observable observable,Object arg);
[*]
[*]
[*]
[*]}
  
  
  
  
  具体主题:
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20com.scnulh.observer%3B%0A%0A%20%0A%0Aimport%20java.util.ArrayList%3B%0A%0Aimport%20java.util.List%3B%0A%0A%20%0A%0A%2F**%0A%0A%20*%20%E5%85%B7%E4%BD%93%E4%B8%BB%E9%A2%98%EF%BC%8C%E5%81%87%E8%AE%BE%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AATomcat%E7%9A%84%E5%AE%B9%E5%99%A8%E5%9F%BA%E7%B1%BB%0A%0A%20*%20%E6%9C%89%E4%B8%80%E4%B8%AAstart%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BB%A3%E8%A1%A8%E5%AE%B9%E5%99%A8%E7%9A%84%E5%90%AF%E5%8A%A8%EF%BC%8C%E5%9C%A8%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E4%B8%AD%0A%0A%20*%20%E9%80%9A%E7%9F%A5%E6%89%80%E6%9C%89%E8%A7%82%E5%AF%9F%E8%80%85%20%0A%0A%20*%2F%0A%0Apublic%20class%20ContainerBase%20implements%20Observable%7B%0A%0A%20%0A%0A%20%20%20%20%2F%2F%E6%8C%81%E6%9C%89%E8%A7%82%E5%AF%9F%E8%80%85%E7%9A%84List%0A%0A%20%20%20%20private%20List%3CObserver%3E%20observers%3Dnew%20ArrayList%3CObserver%3E()%3B%20%0A%0A%20%0A%0A%20%0A%0A%20%20%20%20%2F%2F%E6%B7%BB%E5%8A%A0%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20%40Override%0A%0A%20%20%20%20public%20void%20addObserver(Observer%20observer)%20%7B%0A%0A%20%20%20%20%20%20%20observers.add(observer)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20%2F%2F%E5%88%A0%E9%99%A4%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20%40Override%0A%0A%20%20%20%20public%20void%20deleteObserver(Observer%20observer)%20%7B%0A%0A%20%20%20%20%20%20%20observers.remove(observer)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20%2F%2F%E9%80%9A%E7%9F%A5%E6%89%80%E6%9C%89%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20%40Override%0A%0A%20%20%20%20public%20void%20notifyObservers()%20%7B%0A%0A%20%20%20%20%20%20%20for(Observer%20observer%3Aobservers)%0A%0A%20%20%20%20%20%20%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20observer.update(this%2C%20%22start%22)%3B%0A%0A%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%0A%0A%20%20%20%20%2F%2F%E5%AE%B9%E5%99%A8%E7%9A%84%E5%90%AF%E5%8A%A8%E6%96%B9%E6%B3%95%EF%BC%8C%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%E5%B9%B6%E8%B0%83%E7%94%A8notifyObservers%E6%96%B9%E6%B3%95%E9%80%9A%E7%9F%A5%E6%89%80%E6%9C%89%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20public%20void%20start()%0A%0A%20%20%20%20%7B%0A%0A%20%20%20%20%20%20%20System.out.println(%22container%20start%22)%3B%0A%0A%20%20%20%20%20%20%20notifyObservers()%3B%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%0A%20%20%20%20%20%20%20%0A%0A%20%20%20%20%20%20%20ContainerBase%20container%3Dnew%20ContainerBase()%3B%2F%2F%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%0A%0A%20%20%20%20%20%20%20Observer%20observer%3Dnew%20ContainerConfig()%3B%20%20%20%20%2F%2F%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E7%9B%91%E5%90%AC%E7%B1%BB%0A%0A%20%20%20%20%20%20%20container.addObserver(observer)%3B%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E4%B8%BA%E5%AE%B9%E5%99%A8%E6%B7%BB%E5%8A%A0%E7%9B%91%E5%90%AC%E7%B1%BB%0A%0A%20%20%20%20%20%20%20container.start()%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%7D%0A%0A
[*]package com.scnulh.observer;
[*]
[*]
[*]
[*]import java.util.ArrayList;
[*]
[*]import java.util.List;
[*]
[*]
[*]
[*]/**
[*]
[*] * 具体主题,假设这是一个Tomcat的容器基类
[*]
[*] * 有一个start方法,代表容器的启动,在启动过程中
[*]
[*] * 通知所有观察者
[*]
[*] */
[*]
[*]public class ContainerBase implements Observable{
[*]
[*]
[*]
[*]    //持有观察者的List
[*]
[*]    private List observers=new ArrayList();
[*]
[*]
[*]
[*]
[*]
[*]    //添加观察者
[*]
[*]    @Override
[*]
[*]    public void addObserver(Observer observer) {
[*]
[*]       observers.add(observer);
[*]
[*]    }
[*]
[*]
[*]
[*]    //删除观察者
[*]
[*]    @Override
[*]
[*]    public void deleteObserver(Observer observer) {
[*]
[*]       observers.remove(observer);
[*]
[*]    }
[*]
[*]
[*]
[*]    //通知所有观察者
[*]
[*]    @Override
[*]
[*]    public void notifyObservers() {
[*]
[*]       for(Observer observer:observers)
[*]
[*]       {
[*]
[*]         observer.update(this, "start");
[*]
[*]       }
[*]
[*]    }
[*]
[*]
[*]
[*]    //容器的启动方法,启动容器并调用notifyObservers方法通知所有观察者
[*]
[*]    public void start()
[*]
[*]    {
[*]
[*]       System.out.println("container start");
[*]
[*]       notifyObservers();
[*]
[*]    }
[*]
[*]
[*]
[*]    public static void main(String[] args) {
[*]
[*]
[*]
[*]       ContainerBase container=new ContainerBase();//声明一个容器
[*]
[*]       Observer observer=new ContainerConfig();    //声明一个监听类
[*]
[*]       container.addObserver(observer);            //为容器添加监听类
[*]
[*]       container.start();                        //启动容器
[*]
[*]
[*]
[*]    }
[*]
[*]
[*]
[*]}
  
  
  
  
  
  具体观察者:
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20com.scnulh.observer%3B%0A%0A%20%0A%0A%2F**%0A%0A%20*%20%E5%85%B7%E4%BD%93%E8%A7%82%E5%AF%9F%E8%80%85%EF%BC%8C%E5%81%87%E8%AE%BE%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AE%B9%E5%99%A8%E7%9A%84%E7%9B%91%E5%90%AC%E7%B1%BB%EF%BC%8C%0A%0A%20*%20%E5%9C%A8tomcat%E5%AE%B9%E5%99%A8%E5%90%AF%E5%8A%A8%E6%97%B6%EF%BC%8C%E5%A4%84%E7%90%86tomcat%E7%9A%84%E9%85%8D%E7%BD%AE%0A%0A%20*%2F%0A%0Apublic%20class%20ContainerConfig%20implements%20Observer%7B%0A%0A%20%0A%0A%20%20%20%20%40Override%0A%0A%20%20%20%20public%20void%20update(Observable%20observable%2C%20Object%20arg)%20%7B%0A%0A%20%20%20%20%20%20%20String%20event%3D(String)%20arg%3B%0A%0A%20%20%20%20%20%20%20if(event.equals(%22start%22))%0A%0A%20%20%20%20%20%20%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20System.out.println(%22container%20starting%2C%20do%20container%20configs%22)%3B%0A%0A%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%7D%0A%0A%7D%0A%0A
[*]package com.scnulh.observer;
[*]
[*]
[*]
[*]/**
[*]
[*] * 具体观察者,假设这是一个容器的监听类,
[*]
[*] * 在tomcat容器启动时,处理tomcat的配置
[*]
[*] */
[*]
[*]public class ContainerConfig implements Observer{
[*]
[*]
[*]
[*]    @Override
[*]
[*]    public void update(Observable observable, Object arg) {
[*]
[*]       String event=(String) arg;
[*]
[*]       if(event.equals("start"))
[*]
[*]       {
[*]
[*]         System.out.println("container starting, do container configs");
[*]
[*]       }
[*]
[*]    }
[*]
[*]}
  
  
  
  
           上述便是观察者模式的简单示例,之所以用ContainerBase和ContainerConfig作为具体主题和观察者,是因为后面要分析tomcat的容器(Container)和监听类(Config)的源代码,这里先模拟下他们的工作方式。
           细心的读者很快就会发现,在具体主题ContainerBaser中,对观察者的管理方法其实是很固定的,无非就是声明一个Observer的集合,提供添加,删除,查找的方法。甚至连在主题发生变化时,通知观察者的方法也是固定的,即轮循的通知每一个观察者。如果每一个实现了主题接口的具体主题都要实现这些方法,无疑会造成重复,带来代码编写上的麻烦。为了消除重复,减少麻烦,可以提供一个类,实现主题对观察者的管理及通知。这正是java util包里Observable与Observer所做的。感兴趣的读者可以出看看,这里就不贴代码了。Tomcat没有直接使用这个Observable类,而是另外实现了一个LifecycleSupport类。
           总的来说,观察者模式还是很好理解的,要让观察者模式用于实际,关键有两点,一点要提供主题与观察者的实现,第二是将观察者注册到具体主题中,这样主题发生变化时,才能通知到观察者。
  
  
  三、Tomcat生命周期管理
  理解了观察者模式,Tomcat的生命周期管理便很容易理解了。所涉及的类有:

[*]
Lifecycle:相当于抽象主题角色,所有的容器类与组件实现类都实现了这个接口。如StandardContext
[*]
LifecycleListener:相当于抽象观察者角色,具体的实现类有ContextConfig, HostConfig, EngineConfig类,它们在容器启动时与停止时触发。
[*]
LifecycleEvent:生命周期事件,对主题与发生的事件进行封装。
[*]
LifecycleSupport:生命周期管理的实用类,提供对观察者的添加,删除及通知观察者的方法。
[*]
LifecycleException:生命周期异常类。
  
  
  Lifecycle接口
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20com.apache.catalina%3B%0A%0A%20%0A%0Aimport%20org.apache.catalina.LifecycleException%3B%0A%0A%20%0A%0Apublic%20interface%20Lifecycle%20%7B%20%20%20%20%0A%0A%20%20%20%20%2F%2F%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%86%85%E7%9A%84%E5%85%AD%E4%B8%AA%E4%BA%8B%E4%BB%B6%0A%0A%20%20%20%20public%20static%20final%20String%20START_EVENT%20%3D%20%22start%22%3B%20%20%20%0A%0A%20%20%20%20public%20static%20final%20String%20BEFORE_START_EVENT%20%3D%20%22before_start%22%3B%0A%0A%20%20%20%20public%20static%20final%20String%20AFTER_START_EVENT%20%3D%20%22after_start%22%3B%20%20%20%0A%0A%20%20%20%20public%20static%20final%20String%20STOP_EVENT%20%3D%20%22stop%22%3B%20%20%20%0A%0A%20%20%20%20public%20static%20final%20String%20BEFORE_STOP_EVENT%20%3D%20%22before_stop%22%3B%20%20%20%20%0A%0A%20%20%20%20public%20static%20final%20String%20AFTER_STOP_EVENT%20%3D%20%22after_stop%22%3B%0A%0A%20%20%20%20%2F%2F%E8%A7%82%E5%AF%9F%E8%80%85%E7%9A%84%E7%AE%A1%E7%90%86%E4%B8%8E%E9%80%9A%E7%9F%A5%E6%96%B9%E6%B3%95%0A%0A%20%20%20%20public%20void%20addLifecycleListener(LifecycleListener%20listener)%3B%0A%0A%20%20%20%20public%20void%20removeLifecycleListener(LifecycleListener%20listener)%3B%0A%0A%20%20%20%20public%20LifecycleListener%5B%5D%20findLifecycleListeners()%3B%0A%0A%20%20%20%20%2F%2F%E4%B8%BB%E9%A2%98%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E5%81%9C%E6%AD%A2%E6%96%B9%E6%B3%95%0A%0A%20%20%20%20public%20void%20start()throws%20LifecycleException%3B%0A%0A%20%20%20%20public%20void%20stop()throws%20LifecycleException%3B%0A%0A%7D%0A%0A
[*]package com.apache.catalina;
[*]
[*]
[*]
[*]import org.apache.catalina.LifecycleException;
[*]
[*]
[*]
[*]public interface Lifecycle {
[*]
[*]    //生命周期内的六个事件
[*]
[*]    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 void addLifecycleListener(LifecycleListener listener);
[*]
[*]    public void removeLifecycleListener(LifecycleListener listener);
[*]
[*]    public LifecycleListener[] findLifecycleListeners();
[*]
[*]    //主题的启动与停止方法
[*]
[*]    public void start()throws LifecycleException;
[*]
[*]    public void stop()throws LifecycleException;
[*]
[*]}
  
  
  
  
  
  Lifecycle相当于观察者模式中的抽象主题角色(Observable),它定义了添加、删除及通知管理者的方法。
  还定义了与生命周期相关的6个事件。Start和stop方法是Lifecycle最重要的两个方法,分别代表启动与停止。所有四种容器的标准实现类(StandardEngine, StandardHost, StandardContext,StandardWrapper)和基本组件(Logger,Loader,Manager等)的实现类都实现了Lifecycle接口,这意义着它们都是具体的观察者,具有启动和停止方法。容器启动时,主要做三件事:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。子容器启动也做这三件事,这样整个Tomcat便启动了。Tomcat的停止也类似。
  
  LifecycleListener接口:
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20org.apache.catalina%3B%0A%0Apublic%20interface%20LifecycleListener%20%7B%0A%0A%20%20%20%20%2F**%0A%0A%20%20%20%20%20*%20Acknowledge%20the%20occurrence%20of%20the%20specified%20event.%0A%0A%20%20%20%20%20*%0A%0A%20%20%20%20%20*%20%40param%20event%20LifecycleEvent%20that%20has%20occurred%0A%0A%20%20%20%20%20*%2F%0A%0A%20%20%20%20public%20void%20lifecycleEvent(LifecycleEvent%20event)%3B%0A%0A%20%0A%0A%7D%0A%0A
[*]package org.apache.catalina;
[*]
[*]public interface LifecycleListener {
[*]
[*]    /**
[*]
[*]   * Acknowledge the occurrence of the specified event.
[*]
[*]   *
[*]
[*]   * @param event LifecycleEvent that has occurred
[*]
[*]   */
[*]
[*]    public void lifecycleEvent(LifecycleEvent event);
[*]
[*]
[*]
[*]}
  
  
  
  
  
  LifecycleListener相当于观察者模式中的抽象观察者角色(Observer),可以看到它与Observer非常的类似,都只有一个更新自己的方法。不同的是,Observer 更新方法中,有两个参数:Observable与Object,而LifecycleListener中只有一个参数LifecycleEvent,这正是对前面两个参数的封装。
  
  LifecycleEvent:
  
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20org.apache.catalina%3B%0A%0A%20%0A%0Aimport%20java.util.EventObject%3B%0A%0A%20%0A%0Apublic%20final%20class%20LifecycleEvent%0A%0A%20%20%20%20extends%20EventObject%20%7B%0A%0A%20%20%20%20%0A%0A%20%20%20%20public%20LifecycleEvent(Lifecycle%20lifecycle%2C%20String%20type)%20%7B%0A%0A%20%20%20%20%20%20%20%20this(lifecycle%2C%20type%2C%20null)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20public%20LifecycleEvent(Lifecycle%20lifecycle%2C%20String%20type%2C%20Object%20data)%20%7B%0A%0A%20%20%20%20%20%20%20%20super(lifecycle)%3B%0A%0A%20%20%20%20%20%20%20%20this.lifecycle%20%3D%20lifecycle%3B%0A%0A%20%20%20%20%20%20%20%20this.type%20%3D%20type%3B%0A%0A%20%20%20%20%20%20%20%20this.data%20%3D%20data%3B%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20private%20Object%20data%20%3D%20null%3B%20%20%20%20%0A%0A%20%20%20%20private%20Lifecycle%20lifecycle%20%3D%20null%3B%20%20%20%20%0A%0A%20%20%20%20private%20String%20type%20%3D%20null%3B%20%20%20%20%0A%0A%20%20%20%20%0A%0A%20%20%20%20public%20Object%20getData()%20%7B%0A%0A%20%20%20%20%20%20%20%20return%20(this.data)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20Lifecycle%20getLifecycle()%20%7B%0A%0A%20%20%20%20%20%20%20%20return%20(this.lifecycle)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20public%20String%20getType()%20%7B%0A%0A%20%20%20%20%20%20%20%20return%20(this.type)%3B%0A%0A%20%20%20%20%7D%0A%0A%7D%0A%0A
[*]package org.apache.catalina;
[*]
[*]
[*]
[*]import java.util.EventObject;
[*]
[*]
[*]
[*]public final class LifecycleEvent
[*]
[*]    extends EventObject {
[*]
[*]
[*]
[*]    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);
[*]
[*]    }
[*]
[*]}
  LifecycleEvent
是对主题(事件源),事件及相关数据的封装,继承自java.util.  
是对主题(事件源),事件及相关数据的封装,继承自java.util.  
  
EventObject.  
  LifecycleSupport:
  前面说过,抽象主题定义的添加,删除和通知观察者的方法都是很固定的,每个实现类实现起来都一样,这样就可以提供一个类来实现这些功能,具体的主题类直接调用便可以了。
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=package%20org.apache.catalina.util%3B%0A%0A%20%0A%0Aimport%20org.apache.catalina.Lifecycle%3B%0A%0Aimport%20org.apache.catalina.LifecycleEvent%3B%0A%0Aimport%20org.apache.catalina.LifecycleListener%3B%0A%0A%20%0A%0Apublic%20final%20class%20LifecycleSupport%20%7B%0A%0A%20%20%20%20public%20LifecycleSupport(Lifecycle%20lifecycle)%20%7B%0A%0A%20%20%20%20%20%20%20%20super()%3B%0A%0A%20%20%20%20%20%20%20%20this.lifecycle%20%3D%20lifecycle%3B%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%0A%0A%20%20%20%20private%20Lifecycle%20lifecycle%20%3D%20null%3B%20%20%0A%0A%20%20%20%20private%20LifecycleListener%20listeners%5B%5D%20%3D%20new%20LifecycleListener%5B0%5D%3B%0A%0A%20%20%20%20%2F%2F%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20public%20void%20addLifecycleListener(LifecycleListener%20listener)%20%7B%0A%0A%20%20%20%20%20%20synchronized%20(listeners)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20LifecycleListener%20results%5B%5D%20%3D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20new%20LifecycleListener%5Blisteners.length%20%2B%201%5D%3B%0A%0A%20%20%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20listeners.length%3B%20i%2B%2B)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5Bi%5D%20%3D%20listeners%5Bi%5D%3B%0A%0A%20%20%20%20%20%20%20%20%20%20results%5Blisteners.length%5D%20%3D%20listener%3B%0A%0A%20%20%20%20%20%20%20%20%20%20listeners%20%3D%20results%3B%0A%0A%20%20%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E6%89%BE%E5%87%BA%E6%89%80%E6%B3%A8%E5%86%8C%E7%9A%84%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20public%20LifecycleListener%5B%5D%20findLifecycleListeners()%20%7B%0A%0A%20%20%20%20%20%20%20%20return%20listeners%3B%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E9%80%9A%E7%9F%A5%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20public%20void%20fireLifecycleEvent(String%20type%2C%20Object%20data)%20%7B%0A%0A%20%0A%0A%20%20%20%20%20%20%20%20LifecycleEvent%20event%20%3D%20new%20LifecycleEvent(lifecycle%2C%20type%2C%20data)%3B%0A%0A%20%20%20%20%20%20%20%20LifecycleListener%20interested%5B%5D%20%3D%20null%3B%0A%0A%20%20%20%20%20%20%20%20synchronized%20(listeners)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20interested%20%3D%20(LifecycleListener%5B%5D)%20listeners.clone()%3B%0A%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20interested.length%3B%20i%2B%2B)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20interested%5Bi%5D.lifecycleEvent(event)%3B%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%20%20%20%20%2F%2F%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E8%A7%82%E5%AF%9F%E8%80%85%0A%0A%20%20%20%20public%20void%20removeLifecycleListener(LifecycleListener%20listener)%20%7B%0A%0A%20%0A%0A%20%20%20%20%20%20%20%20synchronized%20(listeners)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20n%20%3D%20-1%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20listeners.length%3B%20i%2B%2B)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(listeners%5Bi%5D%20%3D%3D%20listener)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20n%20%3D%20i%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(n%20%3C%200)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20LifecycleListener%20results%5B%5D%20%3D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20new%20LifecycleListener%5Blisteners.length%20-%201%5D%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20j%20%3D%200%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20listeners.length%3B%20i%2B%2B)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20!%3D%20n)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5Bj%2B%2B%5D%20%3D%20listeners%5Bi%5D%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20listeners%20%3D%20results%3B%0A%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20%7D%0A%0A%7D%0A%0A
[*]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;
[*]
[*]    //添加一个观察者
[*]
[*]    public void addLifecycleListener(LifecycleListener listener) {
[*]
[*]      synchronized (listeners) {
[*]
[*]          LifecycleListener results[] =
[*]
[*]            new LifecycleListener;
[*]
[*]          for (int i = 0; i < listeners.length; i++)
[*]
[*]            results = listeners;
[*]
[*]          results = listener;
[*]
[*]          listeners = results;
[*]
[*]      }
[*]
[*]
[*]
[*]    }
[*]
[*]    //找出所注册的观察者
[*]
[*]    public LifecycleListener[] findLifecycleListeners() {
[*]
[*]      return listeners;
[*]
[*]
[*]
[*]    }
[*]
[*]    //通知观察者
[*]
[*]    public void fireLifecycleEvent(String type, Object data) {
[*]
[*]
[*]
[*]      LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
[*]
[*]      LifecycleListener interested[] = null;
[*]
[*]      synchronized (listeners) {
[*]
[*]            interested = (LifecycleListener[]) listeners.clone();
[*]
[*]      }
[*]
[*]      for (int i = 0; i < interested.length; i++)
[*]
[*]            interested.lifecycleEvent(event);
[*]
[*]
[*]
[*]    }
[*]
[*]    //删除一个观察者
[*]
[*]    public void removeLifecycleListener(LifecycleListener listener) {
[*]
[*]
[*]
[*]      synchronized (listeners) {
[*]
[*]            int n = -1;
[*]
[*]            for (int i = 0; i < listeners.length; i++) {
[*]
[*]                if (listeners == listener) {
[*]
[*]                  n = i;
[*]
[*]                  break;
[*]
[*]                }
[*]
[*]            }
[*]
[*]            if (n < 0)
[*]
[*]                return;
[*]
[*]            LifecycleListener results[] =
[*]
[*]            new LifecycleListener;
[*]
[*]            int j = 0;
[*]
[*]            for (int i = 0; i < listeners.length; i++) {
[*]
[*]                if (i != n)
[*]
[*]                  results = listeners;
[*]
[*]            }
[*]
[*]            listeners = results;
[*]
[*]      }
[*]
[*]
[*]
[*]    }
[*]
[*]}
  
  
  
  
  
  这样,具体的主题实现抽象主题中对观察者的添加、删除与通知方法便非常简单了。
  如在ContainerBase(容器的基本实现类)中:
  



Java代码 http://scnulh.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf?clipboard=protected%20LifecycleSupport%20lifecycle%20%3D%20new%20LifecycleSupport(this)%3B%0A%0A%20%20%20%20public%20void%20addLifecycleListener(LifecycleListener%20listener)%20%7B%0A%0A%20%20%20%20%20%20%20%20lifecycle.addLifecycleListener(listener)%3B%0A%0A%20%20%20%20%7D%0A%0A%20%0A%0A%20%20%20%20public%20LifecycleListener%5B%5D%20findLifecycleListeners()%20%7B%0A%0A%20%20%20%20%20%20%20%20return%20lifecycle.findLifecycleListeners()%3B%0A%0A%7D%0A%0A%20%0A%0A%20%20%20%20public%20void%20removeLifecycleListener(LifecycleListener%20listener)%20%7B%0A%0A%20%20%20%20%20%20%20%20lifecycle.removeLifecycleListener(listener)%3B%0A%0A%7D%0A%0A
[*]protected LifecycleSupport lifecycle = new LifecycleSupport(this);
[*]
[*]    public void addLifecycleListener(LifecycleListener listener) {
[*]
[*]      lifecycle.addLifecycleListener(listener);
[*]
[*]    }
[*]
[*]
[*]
[*]    public LifecycleListener[] findLifecycleListeners() {
[*]
[*]      return lifecycle.findLifecycleListeners();
[*]
[*]}
[*]
[*]
[*]
[*]    public void removeLifecycleListener(LifecycleListener listener) {
[*]
[*]      lifecycle.removeLifecycleListener(listener);
[*]
[*]}
  
  
  Lifecycle,LifecycleListener,LifecycleSupport,LifecycleEvent, LifecycleException及其具体的观察者与具体的主题之间的关系如下:
  
  
  
  
  
  
  
  
  让我们再来看一下StandardContext的启动方法,StandartContext实现了Lifecycle,它的启动方法由上一级容器所调用。
  public synchronized void start() throws LifecycleException {
  //略过N多代码
  
  //通知观察者,容器即将启动
  lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
  
  //略过N多代码
  // 启动loader,cluster,realm组件
  if ((loader != null) && (loader instanceof Lifecycle))
           ((Lifecycle) loader).start();
  if ((cluster != null) && (cluster instanceof Lifecycle))
           ((Lifecycle) cluster).start();
  if ((realm != null) && (realm instanceof Lifecycle))
           ((Lifecycle) realm).start();
  //略过N多代码
  
  //找出所有的子容器,并且启动
  Container children[] = findChildren();
  for (int i = 0; i < children.length; i++) {
        if (children instanceof Lifecycle)
              ((Lifecycle) children).start();
  }
  
  //通知所有观察者,容器正在启动
  lifecycle.fireLifecycleEvent(START_EVENT, null);
  
  //启动Manager组件
  if ((manager != null) && (manager instanceof Lifecycle))
           ((Lifecycle) manager).start();
  //通知所有观察者,容器已经启动
  lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
  
  }
  这里主要做三件事:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。每一层次的容器都这样启动,最终整个Tomcat启动完毕。
  因为源代码实在是太多了,没法全部贴出来,如果感兴趣,大家可以在附件上下下来研究。
  推荐大家阅读How Tomcat Works这本书。就像书名一样,这本书详细的剖析了Tomcat运作机制,写的非常的好,在豆瓣这本书的评分是9.4分,而同样经典的Thinking in Java为9.1分,Effective Java为9.2分。Tomcat的源代码非常值得研究,里面用了很多的设计模式,如本文讲的观察者模式,还是上一篇所讲的单例模式,以及门面模式,责任链模式等等。
  


[*]HowTomcatWorksApps.zip (3.7 MB)
[*]下载次数: 11
页: [1]
查看完整版本: Tomcat生命周期管理与观察者模式