zoukankan      html  css  js  c++  java
  • tomcat事件处理机制

    最近在阅读“how tomcat works”这本书,结合tomcat7的源码进行学习。对于学习的收获,将通过“tomcat学习系列”记录下来,和大家一起分享和交流,也算对自己学习的一种促进。闲话不多说,正文开始。 
        Catalina内部由多个组件组成,启动时各个组件都需要启动,关闭时需要各个组件关闭。如何协作各个组件的初始化、启动、停止、销毁等的一致性,通过各组件实现Lifecycle这个接口来完成。各组件在启动、关闭等重要生命周期中,会发出事件通知,通知已注册的观察者做事件处理。 

    一、主要类图


    二、主要类介绍 

    1) Lifecycle 
    Lifecycle表示生命周期概念的接口。定义了组件生命周期中的通用事件(START_EVENT、STOP_EVENT等)和接口(start、stop、destroy、addLifecycleListener、removeLifecycleListener等)。组件可以通过实现Lifecyecle接口,完成组建的重要生命周期实现和组建的观察者管理。 
    2)LifecycleState 
    组件的有效状态枚举。定义了组件生命周期中的状态和状态对应的事件。当状态发生改变时,会发出相应事件,通知观察者进行处理。 
    3)LifecycleBase 
    Lifecycle接口的抽象的基础实现类,主要实现了制定启动和停止状态相关的转换规则。Lifecycle接口的默认实现,实现init、start、stop、destroy等方法。对观察者的增加、查找和删除等操作会适配器方式,由组合的LifecycleSupport实例来完成。此外还提供了生成LifecycleEvent事件的接口 
    4)LifecycleSupport 
    用来帮助传送消息给监听器的辅助类。观察者的实际管理类,实现观察者的注册、删除、查询、调用等操作。 
    5)LifecycleListener 
    用来监听组件状态变化并触发相应事件的监听器。生命周期的观察者,定义了观察者的事件处理接口lifecycleEvent(LifecycleEvent event)。 
    6)ServerLifecycleListener 
    实际的观察者,实现了事件处理接口。 
    7)LifecycleEvent 
    组件状态变化时触发的事件。观察者使用的参数,它封装了事件来源、事件类型和事件数据,使得观察者可以按事件来源和事件类型分类处理事件。 

    8)LifecycleException

    生命周期相关异常。

    三、下面分别对这几个类进行解析

    Lifecycle

    这个接口声明了能对组件施加影响的生命周期事件类型常量,可以分为在状态中、状态前和状态后(不是每个状态都有这相应的三种情况)。包含的状态有初始化、启动、停止、销毁、配置,以及一个特殊的阶段性状态,具体常量如下:

        public static final String BEFORE_INIT_EVENT = "before_init";
        public static final String AFTER_INIT_EVENT = "after_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 AFTER_DESTROY_EVENT = "after_destroy";
        public static final String BEFORE_DESTROY_EVENT = "before_destroy";
        public static final String PERIODIC_EVENT = "periodic";
        public static final String CONFIGURE_START_EVENT = "configure_start";
        public static final String CONFIGURE_STOP_EVENT = "configure_stop";

    Lifecycle对外提供的方法主要分为两大类,一类是对监听器的管理,另一类是生命周期的各个状态,需要根据状态来做相应动作和触发事件。

     //监听器的添加、查找与删除操作
        public void addLifecycleListener(LifecycleListener listener);
        public LifecycleListener[] findLifecycleListeners();
        public void removeLifecycleListener(LifecycleListener listener);
    
        //触发各个状态相关的生命周期事件来进行准备和善后处理
        public void init() throws LifecycleException;
        public void start() throws LifecycleException;
        public void stop() throws LifecycleException;
        public void destroy() throws LifecycleException;
    
        //获取组件当前状态
        public LifecycleState getState();
        public String getStateName();

    实现了Lifecycle接口的非常之多,具体可以去看它继承树,这里给出一些实现或继承该接口的关键类或接口。

    lifecycle-hierarchy

    LifecycleListener

    LifecycleListener表示对某一个生命周期事件的监听。这个接口非常简单,只有一个方法。

     //定义某一事件发生时需要的行为
        public void lifecycleEvent(LifecycleEvent event);

    LifecycleEvent

    LifecycleEvent继承自Java的事件对象EventObject,是一个简单的类,由事件相关组件、事件的类型和事件相关数据组成。

    public final class LifecycleEvent extends EventObject {
        private static final long serialVersionUID = 1L;
        private final Object data;
        private final String type;
    
        public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
            super(lifecycle);
            this.type = type;
            this.data = data;
        }
    
        public Object getData() {
            return (this.data);
        }
    
        public Lifecycle getLifecycle() {
            return (Lifecycle) getSource();
        }
    
        public String getType() {
            return (this.type);
        }
    }

    LifecycleException

    LifecycleException表示一个生命周期相关的异常,继承自Java的Exception类,提供了多种不同的构造函数,此外不能自定义它的子类。

    public final class LifecycleException extends Exception {
        private static final long serialVersionUID = 1L;
    
        public LifecycleException() {
            super();
        }
    
        public LifecycleException(String message) {
            super(message);
        }
    
        public LifecycleException(Throwable throwable) {
            super(throwable);
        }
    
        public LifecycleException(String message, Throwable throwable) {
            super(message, throwable);
        }
    }

    LifecycleState

    LifecycleState枚举出了一个组件合法的生命周期状态,并对外提供两个参数,一个是获取生命周期事件,即在该状态下应该调用哪类生命周期事件,另一个是在该状态下能否调用组件除了getter/setter和生命周期方法外的其他public方法。

    public enum LifecycleState {
        NEW(false, null),
        INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
        INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
        STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
        STARTING(true, Lifecycle.START_EVENT),
        STARTED(true, Lifecycle.AFTER_START_EVENT),
        STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
        STOPPING(false, Lifecycle.STOP_EVENT),
        STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
        DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
        DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
        FAILED(false, null),
        MUST_STOP(true, null),
        MUST_DESTROY(false, null);
    
        private final boolean available;
        private final String lifecycleEvent;
    
        private LifecycleState(boolean available, String lifecycleEvent) {
            this.available = available;
            this.lifecycleEvent = lifecycleEvent;
        }
    
        //能否调用其他公共分方法
        public boolean isAvailable() {
            return available;
        }
    
        public String getLifecycleEvent() {
            return lifecycleEvent;
        }
    }

    你会发现在枚举中有很多之前没有提到的状态,下面列出各个状态之间的转换关系:

    state-transfer

    主要状态有:初始(初始状态,初始中,初始后),启动(启动前,启动中,启动后),停止(停止前,停止中,停止后),销毁(销毁前,销毁中,销毁后)

    LifecycleSupport

    LifecycleSupport是用来将事件通知给一个组件的所有监听器的辅助类。它包含了组件和该组件所有的监听器。其中监听器用了线程安全的CopyOnWriteArrayList来存储,主要的事件通知函数如下:

    public void fireLifecycleEvent(String type, Object data) {
            LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
            for (LifecycleListener listener : listeners) {
                listener.lifecycleEvent(event);
            }
        }

    LifecycleBase

    LifecycleBase是实现了Lifecycle的抽象类。它通过持有一个LifecycleSupport来管理监听器。具体的状态函数使用了模板方法模式,LifecycleBase规定了个状态之间的转换规则(是否合法以及状态间的自动转换等,具体参看LifecycleState中的状态转换图),而让用户继承的子类来实现具体的操作。由于代码较多,举一个start方法的例子。

    public final synchronized void start() throws LifecycleException {
    
            if (LifecycleState.STARTING_PREP.equals(state) ||
                    LifecycleState.STARTING.equals(state) ||
                    LifecycleState.STARTED.equals(state)) {
    
                if (log.isDebugEnabled()) {
                    Exception e = new LifecycleException();
                    log.debug(sm.getString("lifecycleBase.alreadyStarted",
                            toString()), e);
                } else if (log.isInfoEnabled()) {
                    log.info(sm.getString("lifecycleBase.alreadyStarted",
                            toString()));
                }
    
                return;
            }
    
            if (state.equals(LifecycleState.NEW)) {
                init();
            } else if (state.equals(LifecycleState.FAILED)){
                stop();
            } else if (!state.equals(LifecycleState.INITIALIZED) &&
                    !state.equals(LifecycleState.STOPPED)) {
                invalidTransition(Lifecycle.BEFORE_START_EVENT);
            }
    
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
    
            try {
                //调用用户实现的方法
                startInternal();
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                setStateInternal(LifecycleState.FAILED, null, false);
                throw new LifecycleException(
                        sm.getString("lifecycleBase.startFail",toString()), t);
            }
    
            if (state.equals(LifecycleState.FAILED) ||
                    state.equals(LifecycleState.MUST_STOP)) {
                stop();
            } else {
                // Shouldn't be necessary but acts as a check that sub-classes are
                // doing what they are supposed to.
                if (!state.equals(LifecycleState.STARTING)) {
                    invalidTransition(Lifecycle.AFTER_START_EVENT);
                }
    
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        }
    
        //用户实现的抽象方法
        protected abstract void startInternal() throws LifecycleException;

    四、生命周期重要过程

    1. 观察者注册 
    观察者的注册可以通过xml方式配置,也可以通过直接调用Lifecycle的观察者添加方法。tomcat配置文件目录conf下面的server.xml中观察者配置如下: 

    Java代码  
    1. <Server port="8005" shutdown="SHUTDOWN">  
    2.   <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />  
    3.   <Listener className="org.apache.catalina.core.JasperListener" />  
    4.   <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  
    5.   <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />  
    6. ...  
    7. </Server>  


    LifecycleSupport的观察者注册代码如下: 

    Java代码  
    1. public final class LifecycleSupport {  
    2.     // 观察者数组  
    3.     private LifecycleListener listeners[] = new LifecycleListener[0];  
    4.     ...  
    5.     public void addLifecycleListener(LifecycleListener listener) {  
    6.   
    7.       synchronized (listenersLock) {  
    8.           LifecycleListener results[] =  
    9.             new LifecycleListener[listeners.length + 1];  
    10.           for (int i = 0; i < listeners.length; i++)  
    11.               results[i] = listeners[i];  
    12.           results[listeners.length] = listener;  
    13.           listeners = results;  
    14.       }  
    15.   
    16.     }  
    17. }  


    观察者是通过数组来维护,每次增加一个新的观察者,都需要将当前数组长度加1,将原来数组内容拷贝到新的数组中。对这里的设计我比较困惑,为什么采用这种数组扩容方式,这样每次增加新增观察者都需要数组拷贝,影响性能。可能的一个原因是,考虑到观察者数目少和新增的次数少,这种方式可以减少内存占用。 

    2. 通知观察者 
    组件的生命周期中状态发生改变时,都会发出事件,通知观察者处理。下面以LifecycleBase中init()方法举例说明。 

    Java代码  
    1. public abstract class LifecycleBase implements Lifecycle {  
    2.     private LifecycleSupport lifecycle = new LifecycleSupport(this);  
    3.     // 当前状态  
    4.     private volatile LifecycleState state = LifecycleState.NEW;  
    5.     public synchronized final void init() throws LifecycleException {  
    6.         if (!state.equals(LifecycleState.NEW)) {  
    7.             invalidTransition(Lifecycle.BEFORE_INIT_EVENT);  
    8.         }  
    9.         // 状态转移到INITIALIZING,会发送事件  
    10.         setState(LifecycleState.INITIALIZING);  
    11.         initInternal();  
    12.         setState(LifecycleState.INITIALIZED);  
    13.     }  
    14.   
    15.     protected synchronized void setState(LifecycleState state, Object data) {  
    16.         ...  
    17.         this.state = state;  
    18.         // state为枚举类型,获取该枚举值对应的事件类型  
    19.         String lifecycleEvent = state.getLifecycleEvent();  
    20.         if (lifecycleEvent != null) {  
    21.             // 发起事件通知  
    22.             fireLifecycleEvent(lifecycleEvent, data);  
    23.         }  
    24.     }  
    25.   
    26.     // 调用LifecycleSupport进行事件处理  
    27.     protected void fireLifecycleEvent(String type, Object data) {  
    28.         lifecycle.fireLifecycleEvent(type, data);  
    29.     }  
    30. }  


    LifecycleSupport中的事件处理方法如下: 

    Java代码  
    1. public void fireLifecycleEvent(String type, Object data) {  
    2.     // 包装事件类型和数据  
    3.     LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);  
    4.     // 循环,通知所有观察者进行事件处理  
    5.     LifecycleListener interested[] = listeners;  
    6.     for (int i = 0; i < interested.length; i++)  
    7.         interested[i].lifecycleEvent(event);  
    8.   
    9. }  



    3. 观察者事件处理 
    以ServerLifecycleListener为例,说明观察者事件处理过程。 
    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) { 
                        ... 
                    } 
                    if( lifecycle instanceof Service ) { 
                       ... 
                    }           
                    if (lifecycle instanceof StandardContext){ 
                        ... 
                    } 
                
            } else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) { 
                    ... 
            } 
        } 

    观察者可以通过事件来源(lifecycle)和事件类型(eventType)对事件分类处理。 

    四、 总结 
    tomcat中事件处理机制比较灵活,在日常工作的设计中值得借鉴,比如下面的业务场景:对客户投诉的创建、撤销、终止等,可以采用如下处理方式: 
    --生命周期管理-- 
    1. 创建统一的投诉业务生命周期Lifecycle,如create、cancel、destroy等。 
    2. 定义投诉业务的状态枚举类(对应tomcat中LifecycleState),枚举类中定义每个状态对应的事件类型。 
    --观察者注册-- 
    3. 创建观察者管理service(对应tomcat中的LifecycleSupport)。观察者列表可以通过spring bean方式注入。 
    --观察者通知-- 
    4. 在生命周期中状态改变时,比如投诉创建时,发送事件通知,调用观察者管理service,通知观察者处理。 
    5. 包装观察者所需要的数据(对应tomcat中的LifecycleEvent),如事件来源、类型等,供观察者使用。 
    --观察者处理-- 
    6. 定义实际观察者,按事件来源和类型分别做业务处理,比如投诉创建时,将投诉发生时用户的业务开通快照记录下来。 

    本文转自:https://blog.csdn.net/u013291394/article/details/50180753  http://learnworld.iteye.com/blog/1013751

  • 相关阅读:
    集合框架之——迭代器并发修改异常ConcurrentModificationException
    Python day 3 (3) 判断与循环
    hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4
    hdu 2473 Junk-Mail Filter(并查集_虚节点)2008 Asia Regional Hangzhou
    hdu 1573 x问题(中国剩余定理)HDU 2007-1 Programming Contest
    hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)
    hdu 2155 小黑的镇魂曲(dp) 2008信息工程学院集训队——选拔赛
    hdu 4081 Qin Shi Huang's National Road System(最小生成树+dp)2011 Asia Beijing Regional Contest
    hdu 3938 Portal(并查集+离线+kruskal)2011 Multi-University Training Contest 10
    hdu 3172 Virtual Friends(并查集)University of Waterloo Local Contest 2008.09
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/8662573.html
Copyright © 2011-2022 走看看