美文网首页Tomcat原理解析
Tomcat生命周期管理与观察者模式

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

作者: 黄金矿工00七 | 来源:发表于2018-08-17 18:28 被阅读0次

    请结合Servlet工作原理阅读
    在这之前,我简单的讲述一下观察者模式:
    观察者模式又叫做发布-订阅(Publish/Subscribe)模式、源-监听(Source/Listener)模式。它定义了一种一对多的依赖关系,一个主题,多个观察者,当主题发生变化的时候,会主动的通知观察者,这样观察者便能针对主题发生的变化,执行某些对应的动作。观察者模式的应用非常广泛,如Java AWT事件模型,Servlet的监听器,Spring事件处理机制以及本文所讲述的Tomcat生命周期管理机制等等。

    • 观察者模式


      图片.png

      实现该模式,通常需要两个过程:

      • 订阅者订阅


        图片.png
      • 发布者发布

        图片.png
        下面我给出一个具体示例:
        抽象主题
    package com.liyaocai;
    
    
    /**
     * 抽象主题 .
     *
     * @author liyaocai
     * @version V1.0
     * @date 2018/8/17 15:31
     * @since 1.8
     */
    public interface Observable {
      /**
       * 添加观察者
       * @author liyaocai
       * @param observer
       * @return
       * @throws
       */
      void addObsrver(Observer observer);
    
      /**
       * 删除观察者
       * @author liyaocai
       * @param observer
       * @return
       * @throws
       */
      void deletebserver(Observer observer);
    
      /**
       * 事件发生,通知观察者
       * @author liyaocai
       */
      void notifybservsers();
    }
    
    

    抽象观察者

    package com.liyaocai;
    
    /**
     * 抽象观察者 .
     *
     * @author liyaocai
     * @version V1.0
     * @date 2018/8/17 15:41
     * @since 1.8
     */
    public interface Observer {
    
      /**
       * 更新方法,观察者根据传入的主题对象获取主题的上下文
       *
       * 根据传入的Object对象判断发生了何种事件
       */
    
      void update(Observable observable, Object arg);
    }
    
    

    具体主题

    package com.liyaocai;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 模拟Tomcat容器 .
     *
     * @author liyaocai
     * @version V1.0
     * @date 2018/8/17 15:36
     * @since 1.8
     */
    
    public class Container implements Observable {
    
      /**
       * 观察者列表
       */
      private List<Observer> observers = new ArrayList<>();
    
      @Override
      public void addObsrver(Observer observer) {
        observers.add(observer);
      }
    
      @Override
      public void deletebserver(Observer observer) {
        observers.remove(observer);
      }
    
      @Override
      public void notifybservsers() {
        for (Observer observer : observers) {
          observer.update(this, "container start");
        }
      }
    
      /**
       * 容器启动方法,并且通知观察者
       * @author liyaocai
       * @param
       * @return
       * @throws
       */
      public void start(){
        System.out.println("container start");
        notifybservsers();
      }
    }
    
    

    具体观察者

    package com.liyaocai;
    
    /**
     * 具体观察者,模拟容器监听类 .
     *
     * @author liyaocai
     * @version V1.0
     * @date 2018/8/17 15:44
     * @since 1.8
     */
    
    public class ContainerConfig implements Observer {
    
      @Override
      public void update(Observable observable, Object arg) {
        String event = (String) arg;
        if (event.equals("container start"))
        {
          System.out.println("container starting");
        //   do container configs
        }
    
      }
    }
    
    

    实际上,监听器模式也是如此,观察者(Observer)相当于事件监听者,被观察者(Observable)相当于事件源和事件,事件源经过事件的封装传给监听器,当事件源触发事件后,监听器接收到事件对象可以回调事件的方法。

    Tomcat的生命周期管理

    在了解了观察者模式之后,我们正式开始了解Tomcat的生命周期管理,在Tomcat的源码中,下面是相关的类:

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

    Lifecycle相当于观察者模式中的抽象主题角色(Observable),它定义了添加、删除及通知管理者的方法。并且定义了13个与生命周期相关的事件,Start和stop方法是Lifecycle最重要的两个方法,分别代表启动与停止。所有四种容器的标准实现类(StandardEngine, StandardHost, StandardContext,StandardWrapper)和基本组件(Logger,Loader,Manager等)的实现类都实现了Lifecycle接口。容器启动时,主要做三件事:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。子容器启动也做这三件事,这样整个Tomcat便启动了。

    public interface Lifecycle {
    
    
        // ----------------------------------------------------- Manifest Constants
    
    
        /**
         * The LifecycleEvent type for the "component before init" event.
         */
        public static final String BEFORE_INIT_EVENT = "before_init";
    
    
        /**
         * The LifecycleEvent type for the "component after init" event.
         */
        public static final String AFTER_INIT_EVENT = "after_init";
    
    
        /**
         * The LifecycleEvent type for the "component start" event.
         */
        public static final String START_EVENT = "start";
    
    
        /**
         * The LifecycleEvent type for the "component before start" event.
         */
        public static final String BEFORE_START_EVENT = "before_start";
    
    
        /**
         * The LifecycleEvent type for the "component after start" event.
         */
        public static final String AFTER_START_EVENT = "after_start";
    
    
        /**
         * The LifecycleEvent type for the "component stop" event.
         */
        public static final String STOP_EVENT = "stop";
    
    
        /**
         * The LifecycleEvent type for the "component before stop" event.
         */
        public static final String BEFORE_STOP_EVENT = "before_stop";
    
    
        /**
         * The LifecycleEvent type for the "component after stop" event.
         */
        public static final String AFTER_STOP_EVENT = "after_stop";
    
    
        /**
         * The LifecycleEvent type for the "component after destroy" event.
         */
        public static final String AFTER_DESTROY_EVENT = "after_destroy";
    
    
        /**
         * The LifecycleEvent type for the "component before destroy" event.
         */
        public static final String BEFORE_DESTROY_EVENT = "before_destroy";
    
    
        /**
         * The LifecycleEvent type for the "periodic" event.
         */
        public static final String PERIODIC_EVENT = "periodic";
    
    
        /**
         * The LifecycleEvent type for the "configure_start" event. Used by those
         * components that use a separate component to perform configuration and
         * need to signal when configuration should be performed - usually after
         * {@link #BEFORE_START_EVENT} and before {@link #START_EVENT}.
         */
        public static final String CONFIGURE_START_EVENT = "configure_start";
    
    
        /**
         * The LifecycleEvent type for the "configure_stop" event. Used by those
         * components that use a separate component to perform configuration and
         * need to signal when de-configuration should be performed - usually after
         * {@link #STOP_EVENT} and before {@link #AFTER_STOP_EVENT}.
         */
        public static final String CONFIGURE_STOP_EVENT = "configure_stop";
    
    
        // --------------------------------------------------------- Public Methods
    
    
        /**
         * Add a LifecycleEvent listener to this component.
         *
         * @param listener The listener to add
         */
        public void addLifecycleListener(LifecycleListener listener);
    
    
        /**
         * Get the life cycle listeners associated with this life cycle.
         *
         * @return An array containing the life cycle listeners associated with this
         *         life cycle. If this component has no listeners registered, a
         *         zero-length array is returned.
         */
        public LifecycleListener[] findLifecycleListeners();
    
    
        /**
         * Remove a LifecycleEvent listener from this component.
         *
         * @param listener The listener to remove
         */
        public void removeLifecycleListener(LifecycleListener listener);
    
    
        /**
         * Prepare the component for starting. This method should perform any
         * initialization required post object creation. The following
         * {@link LifecycleEvent}s will be fired in the following order:
         * <ol>
         *   <li>INIT_EVENT: On the successful completion of component
         *                   initialization.</li>
         * </ol>
         *
         * @exception LifecycleException if this component detects a fatal error
         *  that prevents this component from being used
         */
        public void init() throws LifecycleException;
    
        /**
         * Prepare for the beginning of active use of the public methods other than
         * property getters/setters and life cycle methods of this component. This
         * method should be called before any of the public methods other than
         * property getters/setters and life cycle methods of this component are
         * utilized. The following {@link LifecycleEvent}s will be fired in the
         * following order:
         * <ol>
         *   <li>BEFORE_START_EVENT: At the beginning of the method. It is as this
         *                           point the state transitions to
         *                           {@link LifecycleState#STARTING_PREP}.</li>
         *   <li>START_EVENT: During the method once it is safe to call start() for
         *                    any child components. It is at this point that the
         *                    state transitions to {@link LifecycleState#STARTING}
         *                    and that the public methods other than property
         *                    getters/setters and life cycle methods may be
         *                    used.</li>
         *   <li>AFTER_START_EVENT: At the end of the method, immediately before it
         *                          returns. It is at this point that the state
         *                          transitions to {@link LifecycleState#STARTED}.
         *                          </li>
         * </ol>
         *
         * @exception LifecycleException if this component detects a fatal error
         *  that prevents this component from being used
         */
        public void start() throws LifecycleException;
    
    
        /**
         * Gracefully terminate the active use of the public methods other than
         * property getters/setters and life cycle methods of this component. Once
         * the STOP_EVENT is fired, the public methods other than property
         * getters/setters and life cycle methods should not be used. The following
         * {@link LifecycleEvent}s will be fired in the following order:
         * <ol>
         *   <li>BEFORE_STOP_EVENT: At the beginning of the method. It is at this
         *                          point that the state transitions to
         *                          {@link LifecycleState#STOPPING_PREP}.</li>
         *   <li>STOP_EVENT: During the method once it is safe to call stop() for
         *                   any child components. It is at this point that the
         *                   state transitions to {@link LifecycleState#STOPPING}
         *                   and that the public methods other than property
         *                   getters/setters and life cycle methods may no longer be
         *                   used.</li>
         *   <li>AFTER_STOP_EVENT: At the end of the method, immediately before it
         *                         returns. It is at this point that the state
         *                         transitions to {@link LifecycleState#STOPPED}.
         *                         </li>
         * </ol>
         *
         * Note that if transitioning from {@link LifecycleState#FAILED} then the
         * three events above will be fired but the component will transition
         * directly from {@link LifecycleState#FAILED} to
         * {@link LifecycleState#STOPPING}, bypassing
         * {@link LifecycleState#STOPPING_PREP}
         *
         * @exception LifecycleException if this component detects a fatal error
         *  that needs to be reported
         */
        public void stop() throws LifecycleException;
    
        /**
         * Prepare to discard the object. The following {@link LifecycleEvent}s will
         * be fired in the following order:
         * <ol>
         *   <li>DESTROY_EVENT: On the successful completion of component
         *                      destruction.</li>
         * </ol>
         *
         * @exception LifecycleException if this component detects a fatal error
         *  that prevents this component from being used
         */
        public void destroy() throws LifecycleException;
    
    
        /**
         * Obtain the current state of the source component.
         *
         * @return The current state of the source component.
         */
        public LifecycleState getState();
    
    
        /**
         * Obtain a textual representation of the current component state. Useful
         * for JMX. The format of this string may vary between point releases and
         * should not be relied upon to determine component state. To determine
         * component state, use {@link #getState()}.
         *
         * @return The name of the current component state.
         */
        public String getStateName();
    
    
        /**
         * Marker interface used to indicate that the instance should only be used
         * once. Calling {@link #stop()} on an instance that supports this interface
         * will automatically call {@link #destroy()} after {@link #stop()}
         * completes.
         */
        public interface SingleUse {
        }
    }
    

    我们来看一下具体的启动过程,

    @Override
    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);
        }
    
        try {
        //  设置生命状态
        setStateInternal(LifecycleState.STARTING_PREP, null, false);
        //启动容器,调用子容器的启动方法,启动子容器,通知容器观察者(由具体容器实现)
        startInternal();
        if (state.equals(LifecycleState.FAILED)) {
        // This is a 'controlled' failure. The component put itself into the
        // FAILED state so call stop() to complete the clean-up.
        stop();
        } else if (!state.equals(LifecycleState.STARTING)) {
        // Shouldn't be necessary but acts as a check that sub-classes are
        // doing what they are supposed to.
        invalidTransition(Lifecycle.AFTER_START_EVENT);
        } else {
        setStateInternal(LifecycleState.STARTED, null, false);
        }
        } catch (Throwable t) {
        // This is an 'uncontrolled' failure so put the component into the
        // FAILED state and throw an exception.
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
        }
        }
    
    
    LifecycleListener接口
    public interface LifecycleListener {
    
    
        /**
         * Acknowledge the occurrence of the specified event.
         *
         * @param event LifecycleEvent that has occurred
         */
        public void lifecycleEvent(LifecycleEvent event);
    
    
    }
    

    LifecycleListener接口提供了一个更新方法,监听器通过事件类型来做出响应操作,与上面的示例代码的观察者模式相比(一种变形),Event封装了事件源(也就是具体主题与事件的类型)。

    LifecycleEvent

    我们来看一下是如何封装的,

    public final class LifecycleEvent extends EventObject {
    
        private static final long serialVersionUID = 1L;
    
    
        /**
         * Construct a new LifecycleEvent with the specified parameters.
         *
         * @param lifecycle Component on which this event occurred
         * @param type Event type (required)
         * @param data Event data (if any)
         */
        public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
            super(lifecycle);
            this.type = type;
            this.data = data;
        }
    
    
        /**
         * The event data associated with this event.
         */
        private final Object data;
    
    
        /**
         * The event type this instance represents.
         */
        private final String type;
    
    
        /**
         * @return the event data of this event.
         */
        public Object getData() {
            return data;
        }
    
    
        /**
         * @return the Lifecycle on which this event occurred.
         */
        public Lifecycle getLifecycle() {
            return (Lifecycle) getSource();
        }
    
    
        /**
         * @return the event type of this event.
         */
        public String getType() {
            return this.type;
        }
    }
    
    

    可以看出,事件封装了事件源(具体的主题)、事件的类型以及需要事件的数据。
    最后总结一下:tomcat的启动过程:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。每一层次的容器都这样启动,最终整个Tomcat启动完毕。

    相关文章

      网友评论

        本文标题:Tomcat生命周期管理与观察者模式

        本文链接:https://www.haomeiwen.com/subject/ftrtiftx.html