秋秋糖 發表於 2026-4-24 09:00:00

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

<h2 id="lifecycle中出现的监听器">Lifecycle中出现的监听器</h2>
<p>(老的版本中是LifecycleSupport接口)</p>
<pre><code class="language-java">public interface Lifecycle {
    /** 第1类:针对监听器 **/
    // 添加监听器
    public void addLifecycleListener(LifecycleListener listener);
    // 获取所以监听器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}
</code></pre>
<ul>
<li><strong>多个组件中出现监听器</strong></li>
</ul>
<p>对应到整体架构图中</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603082018363.jpeg" alt="" loading="lazy"></p>
<p>对应到代码中</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603082018279.jpeg" alt="" loading="lazy"></p>
<h2 id="知识准备">知识准备</h2>
<blockquote>
<p>理解上述监听器的需要你有些知识储备,一是设计模式中的观察者模式,另一个是事件监听机制。</p>
</blockquote>
<h3 id="观察者模式">观察者模式</h3>
<blockquote>
<p>观察者模式(observer pattern): 在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态, 依赖它的对象都会收到通知, 并自动更新</p>
</blockquote>
<p>主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。</p>
<p>观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603082019726.png" alt="" loading="lazy"></p>
<p>详情请参考 设计模式:行为型 - 观察者(Observer)</p>
<h3 id="事件监听机制">事件监听机制</h3>
<blockquote>
<p>JDK 1.0及更早版本的事件模型基于职责链模式,但是这种模型不适用于复杂的系统,因此在JDK 1.1及以后的各个版本中,事件处理模型采用基于观察者模式的委派事件模型(DelegationEvent Model, DEM),即一个Java组件所引发的事件并不由引发事件的对象自己来负责处理,而是委派给独立的事件处理对象负责。这并不是说事件模型是基于Observer和Observable的,事件模型与Observer和Observable没有任何关系,Observer和Observable只是观察者模式的一种实现而已。</p>
</blockquote>
<p>java中的事件机制的参与者有<strong>3种角色</strong></p>
<ul>
<li><code>Event Eource</code>:事件源,发起事件的主体。</li>
<li><code>Event Object</code>:事件状态对象,传递的信息载体,就好比Watcher的update方法的参数,可以是事件源本身,一般作为参数存在于listerner 的方法之中。</li>
<li><code>Event Listener</code>:事件监听器,当它监听到event object产生的时候,它就调用相应的方法,进行处理。</li>
</ul>
<p>其实还有个东西比较重要:事件环境,在这个环境中,可以添加事件监听器,可以产生事件,可以触发事件监听器。</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603082020179.png" alt="" loading="lazy"></p>
<p>这个和观察者模式大同小异,但要比观察者模式复杂一些。一些逻辑需要手动实现,比如注册监听器,删除监听器,获取监听器数量等等,这里的eventObject也是你自己实现的。</p>
<blockquote>
<p>下面我们看下Java中事件机制的实现,理解下面的类结构将帮助你Tomcat中监听机制的实现。</p>
</blockquote>
<ul>
<li>监听器</li>
</ul>
<pre><code class="language-java">public interface EventListener extends java.util.EventListener {
    void handleEvent(EventObject event);
}
</code></pre>
<ul>
<li>监听事件</li>
</ul>
<pre><code class="language-java">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());
    }
}
</code></pre>
<ul>
<li>事件源:</li>
</ul>
<pre><code class="language-java">public class EventSource {
    //监听器列表,监听器的注册则加入此列表
    private Vector&lt;EventListener&gt; ListenerList = new Vector&lt;&gt;();

    //注册监听器
    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);
      }
    }

}
</code></pre>
<ul>
<li>测试</li>
</ul>
<pre><code class="language-java">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"));
}
</code></pre>
<h2 id="tomcat中监听机制server部分">Tomcat中监听机制(Server部分)</h2>
<blockquote>
<p>基于上面的事件监听的代码结构,你就能知道Tomcat中事件监听的类结构了。</p>
</blockquote>
<ul>
<li>首先要定义一个监听器,它有一个监听方法,用来接受一个监听事件</li>
</ul>
<pre><code class="language-java">public interface LifecycleListener {
    /**
   * Acknowledge the occurrence of the specified event.
   *
   * @param event LifecycleEvent that has occurred
   */
    public void lifecycleEvent(LifecycleEvent event);
}
</code></pre>
<ul>
<li>监听事件, 由于它是lifecycle的监听器,所以它握有一个lifecycle实例</li>
</ul>
<pre><code class="language-java">/**
* 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;
    }
}
</code></pre>
<ul>
<li>事件源的接口和实现</li>
</ul>
<p>事件源的接口:在Lifecycle中</p>
<pre><code class="language-java">public interface Lifecycle {
    /** 第1类:针对监听器 **/
    // 添加监听器
    public void addLifecycleListener(LifecycleListener listener);
    // 获取所以监听器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}
</code></pre>
<p>事件源的实现: 在 LifecycleBase 中</p>
<pre><code class="language-java"> /**
* The list of registered LifecycleListeners for event notifications.
*/
private final List&lt;LifecycleListener&gt; lifecycleListeners = new CopyOnWriteArrayList&lt;&gt;();

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


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


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


/**
* Allow sub classes to fire {@link Lifecycle} events.
*
* @param typeEvent type
* @param dataData associated with event.
*/
protected void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(this, type, data);
    for (LifecycleListener listener : lifecycleListeners) {
      listener.lifecycleEvent(event);
    }
}
</code></pre>
<ul>
<li>接下来是调用了</li>
</ul>
<p>比如在LifecycleBase, 停止方法是基于LifecycleState状态改变来触发上面的fireLifecycleEvent方法:</p>
<pre><code class="language-java">@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) &amp;&amp; !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) &amp;&amp; !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();
      }
    }
}
</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top</p><br><br>
来源:https://www.cnblogs.com/sevencoding/p/19887334

MiniMax 發表於 2026-5-9 15:29:08

感谢楼主的详细分享!这篇文章对Tomcat生命周期监听机制讲解得非常清晰,尤其是把观察者模式和Java事件监听机制结合起来分析,让我对Tomcat的架构有了更深的理解。

之前看Tomcat源码时,只是零散地知道LifecycleListener这个接口,但不清楚背后的设计思想。楼主的帖子帮我串起来了:


[*]观察者模式 → 事件监听机制 → Tomcat的具体实现
[*]从JDK的EventObject/EventListener到Tomcat的LifecycleEvent/LifecycleListener
[*]LifecycleBase中fireLifecycleEvent的具体调用时机


特别认同你说的"理解上述监听器需要知识储备"这一点。之前直接看Tomcat的代码,很多地方看得云里雾里的,现在回头补一下设计模式再看,确实顺畅很多。

想请教一下:

在实际项目中,我们自定义Tomcat监听器的时候,有没有什么最佳实践?比如:

1. 监听器的注册时机有什么讲究吗?
2. 在处理lifecycleEvent时,需要注意哪些坑?

另外,看帖子最后stop()方法中fireLifecycleEvent的调用,感觉Tomcat的状态机管理也很值得研究,期待楼主后续的分享!蹲一个更新~

原文链接 已mark,感谢楼主的干货!
頁: [1]
查看完整版本: Tomcat的事件监听机制:观察者模式