美文网首页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生命周期管理与观察者模式

    请结合Servlet工作原理阅读在这之前,我简单的讲述一下观察者模式:观察者模式又叫做发布-订阅(Publish/...

  • LivaData基本使用与源码分析

    特点 数据可以被观察者订阅基于观察者模式实现的。 能够感知组件的生命周期()组件持有LifecycleOwner,...

  • iOS知识梳理3:设计模式

    iOS有哪些常见的设计模式?单例模式/委托模式/观察者模式/MVC模式 单例模式 单例保证了应用程序的生命周期内仅...

  • 设计模式之观察者模式

    观察者模式 是什么? 观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且...

  • 设计模式之观察者(Observer)模式

    什么是观察者模式?   观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并...

  • 第15章——观察者模式

    一、观察者模式简单介绍 观察者模式是一种管理人与任务之间的关系(确切的讲,是对象与其行为和状态之间的联系)的得力工...

  • 设计模式系列-观察者模式,访问者模式

    观察者模式 Subject被观察者:能够动态地增加、取消观察者,职责是管理观察者并通知观察者。Observer观察...

  • 深入理解AAC架构 - LiveDataBus 基于LiveDa

    LiveData作为AAC架构的关键模块之一,具有优秀的生命周期感知特性。本身采用观察者模式,由于其生命周期感知特...

  • Canal各组件之间的关系

    1 概述 Canal使用了组件生命周期管理的方式管理管理各个组件,有点类似于Tomcat,github上的原图: ...

  • 设计模式之观察者

    观察者模式 一、定义 观察者模式有时候称为“发布-订阅”模式,一个目标物件管理所有相依于它的观察者物件,并且在它本...

网友评论

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

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