Tomcat的事件监听机制:观察者模式

Lifecycle中出现的监听器

(老的版本中是LifecycleSupport接口)

复制代码
public interface Lifecycle {
    /** 第1类:针对监听器 **/
    // 添加监听器
    public void addLifecycleListener(LifecycleListener listener);
    // 获取所以监听器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}
  • 多个组件中出现监听器

对应到整体架构图中

对应到代码中

知识准备

理解上述监听器的需要你有些知识储备,一是设计模式中的观察者模式,另一个是事件监听机制。

观察者模式

观察者模式(observer pattern): 在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态, 依赖它的对象都会收到通知, 并自动更新

主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。

观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。

事件监听机制

JDK 1.0及更早版本的事件模型基于职责链模式,但是这种模型不适用于复杂的系统,因此在JDK 1.1及以后的各个版本中,事件处理模型采用基于观察者模式的委派事件模型(DelegationEvent Model, DEM),即一个Java组件所引发的事件并不由引发事件的对象自己来负责处理,而是委派给独立的事件处理对象负责。这并不是说事件模型是基于Observer和Observable的,事件模型与Observer和Observable没有任何关系,Observer和Observable只是观察者模式的一种实现而已。

java中的事件机制的参与者有3种角色

  • Event Eource:事件源,发起事件的主体。

  • Event Object:事件状态对象,传递的信息载体,就好比Watcher的update方法的参数,可以是事件源本身,一般作为参数存在于listerner 的方法之中。

  • Event Listener:事件监听器,当它监听到event object产生的时候,它就调用相应的方法,进行处理。

其实还有个东西比较重要:事件环境,在这个环境中,可以添加事件监听器,可以产生事件,可以触发事件监听器。

这个和观察者模式大同小异,但要比观察者模式复杂一些。一些逻辑需要手动实现,比如注册监听器,删除监听器,获取监听器数量等等,这里的eventObject也是你自己实现的。

下面我们看下Java中事件机制的实现,理解下面的类结构将帮助你Tomcat中监听机制的实现。

  • 监听器

    public interface EventListener extends java.util.EventListener {
    void handleEvent(EventObject event);
    }

  • 监听事件

    public class EventObject extends java.util.EventObject{
    private static final long serialVersionUID = 1L;
    public EventObject(Object source){
    super(source);
    }
    public void doEvent(){
    System.out.println("通知一个事件源 source :"+ this.getSource());
    }
    }

  • 事件源:

    public class EventSource {
    //监听器列表,监听器的注册则加入此列表
    private Vector<EventListener> ListenerList = new Vector<>();

    复制代码
      //注册监听器
      public void addListener(EventListener eventListener) {
          ListenerList.add(eventListener);
      }
    
      //撤销注册
      public void removeListener(EventListener eventListener) {
          ListenerList.remove(eventListener);
      }
    
      //接受外部事件
      public void notifyListenerEvents(EventObject event) {
          for (EventListener eventListener : ListenerList) {
              eventListener.handleEvent(event);
          }
      }

    }

  • 测试

    public static void main(String[] args) {
    EventSource eventSource = new EventSource();
    eventSource.addListener(new EventListener() {
    @Override
    public void handleEvent(EventObject event) {
    event.doEvent();
    if (event.getSource().equals("closeWindows")) {
    System.out.println("doClose");
    }
    }
    });
    eventSource.addListener(new EventListener() {
    @Override
    public void handleEvent(EventObject event) {
    System.out.println("gogogo");
    }
    });
    /*
    * 传入openWindows事件,通知listener,事件监听器,
    对open事件感兴趣的listener将会执行
    **/
    eventSource.notifyListenerEvents(new EventObject("openWindows"));
    }

Tomcat中监听机制(Server部分)

基于上面的事件监听的代码结构,你就能知道Tomcat中事件监听的类结构了。

  • 首先要定义一个监听器,它有一个监听方法,用来接受一个监听事件

    public interface LifecycleListener {
    /**
    * Acknowledge the occurrence of the specified event.
    *
    * @param event LifecycleEvent that has occurred
    */
    public void lifecycleEvent(LifecycleEvent event);
    }

  • 监听事件, 由于它是lifecycle的监听器,所以它握有一个lifecycle实例

    /**

    • General event for notifying listeners of significant changes on a component

    • that implements the Lifecycle interface.

    • @author Craig R. McClanahan
      */
      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;
        }
        }
  • 事件源的接口和实现

事件源的接口:在Lifecycle中

复制代码
public interface Lifecycle {
    /** 第1类:针对监听器 **/
    // 添加监听器
    public void addLifecycleListener(LifecycleListener listener);
    // 获取所以监听器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}

事件源的实现: 在 LifecycleBase 中

复制代码
 /**
  * The list of registered LifecycleListeners for event notifications.
  */
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

/**
  * {@inheritDoc}
  */
@Override
public void addLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.add(listener);
}


/**
  * {@inheritDoc}
  */
@Override
public LifecycleListener[] findLifecycleListeners() {
    return lifecycleListeners.toArray(new LifecycleListener[0]);
}


/**
  * {@inheritDoc}
  */
@Override
public void removeLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.remove(listener);
}


/**
  * Allow sub classes to fire {@link Lifecycle} events.
  *
  * @param type  Event type
  * @param data  Data associated with event.
  */
protected void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(this, type, data);
    for (LifecycleListener listener : lifecycleListeners) {
        listener.lifecycleEvent(event);
    }
}
  • 接下来是调用了

比如在LifecycleBase, 停止方法是基于LifecycleState状态改变来触发上面的fireLifecycleEvent方法:

复制代码
@Override
public final synchronized void stop() throws LifecycleException {

    if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
            LifecycleState.STOPPED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
        } else if (log.isInfoEnabled()) {
            log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
        }

        return;
    }

    if (state.equals(LifecycleState.NEW)) {
        state = LifecycleState.STOPPED;
        return;
    }

    if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
        invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
    }

    try {
        if (state.equals(LifecycleState.FAILED)) {
            // 看这里
            fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        } else {
            setStateInternal(LifecycleState.STOPPING_PREP, null, false);
        }

        stopInternal();

        // Shouldn't be necessary but acts as a check that sub-classes are
        // doing what they are supposed to.
        if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
            invalidTransition(Lifecycle.AFTER_STOP_EVENT);
        }

        setStateInternal(LifecycleState.STOPPED, null, false);
    } catch (Throwable t) {
        handleSubClassException(t, "lifecycleBase.stopFail", toString());
    } finally {
        if (this instanceof Lifecycle.SingleUse) {
            // Complete stop process first
            setStateInternal(LifecycleState.STOPPED, null, false);
            destroy();
        }
    }
}

文章转载自: 程序员Seven

原文链接: https://www.cnblogs.com/sevencoding/p/19887334

体验地址: http://www.jnpfsoft.com/?from=424

相关推荐
ximu_polaris2 小时前
设计模式(C++)-行为型模式-观察者模式
c++·观察者模式·设计模式
QC班长9 小时前
Maven公司私库配置踩坑点
java·服务器·maven·intellij-idea
Makoto_Kimur9 小时前
java开发面试-AI Coding速成
java·开发语言
wuqingshun3141599 小时前
说说mybatis的缓存机制
java·缓存·mybatis
空中海10 小时前
Kubernetes 生产实践、可观测性与扩展入门
java·贪心算法·kubernetes
Devin~Y10 小时前
大厂Java面试实录:Spring Boot/Cloud、Kafka、Redis、K8s 与 Spring AI(RAG/Agent)三轮连环问
java·spring boot·redis·mysql·spring cloud·kafka·kubernetes
bLEd RING10 小时前
SpringBoot3.3.0集成Knife4j4.5.0实战
java
小松加哲10 小时前
Spring MVC 核心原理全解析
java·spring·mvc
Ulyanov11 小时前
《PySide6 GUI开发指南:QML核心与实践》 第二篇:QML语法精要——构建声明式UI的基础
java·开发语言·javascript·python·ui·gui·雷达电子对抗系统仿真