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

相关推荐
AC赳赳老秦几秒前
文案策划提效:OpenClaw批量生成活动文案、宣传海报配文,适配不同渠道调性
java·大数据·服务器·人工智能·python·deepseek·openclaw
_codemonster4 分钟前
系统分析师系列目录
java·网络·数据库
带刺的坐椅19 分钟前
Spring AI 2.0 GA 倒计时:先别急,来看看 Java AI 框架的另一条路
java·spring·ai·llm·agent·solon
TE-茶叶蛋41 分钟前
Java 8 引入的Stream API-stream()
java·windows·python
Stream_Silver43 分钟前
【 libusb4java实战:跨平台USB设备通信完全指南】
java·笔记·嵌入式硬件·microsoft
极光代码工作室1 小时前
基于SpringBoot的宿舍管理系统
java·springboot·web开发·后端开发
Ting-yu1 小时前
SpringCloud快速入门(8)---- OpenFeign(远程调用)
java·spring·spring cloud
两年半的个人练习生^_^1 小时前
什么是内存泄漏?什么是内存溢出?
java·开发语言
曦夜日长1 小时前
C++ STL容器string(二):删除与插入、数据查找、自定义输入
java·开发语言·c++
赏金术士1 小时前
Kotlin 协程底层原理(Continuation)详解
java·开发语言·kotlin