最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Tomcat的事件監(jiān)聽機制:觀察者模式詳解

 更新時間:2026年04月28日 08:53:47   作者:SevenCoding  
本文主要解釋了Java中的事件監(jiān)聽機制及其與觀察者模式的關(guān)系,并具體分析了Tomcat中基于Lifecycle的監(jiān)聽機制,感興趣的朋友跟隨小編一起看看吧

Lifecycle中出現(xiàn)的監(jiān)聽器

(老的版本中是LifecycleSupport接口)

public interface Lifecycle {
    /** 第1類:針對監(jiān)聽器 **/
    // 添加監(jiān)聽器
    public void addLifecycleListener(LifecycleListener listener);
    // 獲取所以監(jiān)聽器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某個監(jiān)聽器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}
  • 多個組件中出現(xiàn)監(jiān)聽器

對應(yīng)到整體架構(gòu)圖中

對應(yīng)到代碼中

知識準備

理解上述監(jiān)聽器的需要你有些知識儲備,一是設(shè)計模式中的觀察者模式,另一個是事件監(jiān)聽機制。

觀察者模式

觀察者模式(observer pattern): 在對象之間定義一對多的依賴, 這樣一來, 當一個對象改變狀態(tài), 依賴它的對象都會收到通知, 并自動更新

主題(Subject)具有注冊和移除觀察者、并通知所有觀察者的功能,主題是通過維護一張觀察者列表來實現(xiàn)這些操作的。

觀察者(Observer)的注冊功能需要調(diào)用主題的 registerObserver() 方法。

詳情請參考 設(shè)計模式:行為型 - 觀察者(Observer)

事件監(jiān)聽機制

JDK 1.0及更早版本的事件模型基于職責鏈模式,但是這種模型不適用于復雜的系統(tǒng),因此在JDK 1.1及以后的各個版本中,事件處理模型采用基于觀察者模式的委派事件模型(DelegationEvent Model, DEM),即一個Java組件所引發(fā)的事件并不由引發(fā)事件的對象自己來負責處理,而是委派給獨立的事件處理對象負責。這并不是說事件模型是基于Observer和Observable的,事件模型與Observer和Observable沒有任何關(guān)系,Observer和Observable只是觀察者模式的一種實現(xiàn)而已。

java中的事件機制的參與者有3種角色

  • Event Eource:事件源,發(fā)起事件的主體。
  • Event Object:事件狀態(tài)對象,傳遞的信息載體,就好比Watcher的update方法的參數(shù),可以是事件源本身,一般作為參數(shù)存在于listerner 的方法之中。
  • Event Listener:事件監(jiān)聽器,當它監(jiān)聽到event object產(chǎn)生的時候,它就調(diào)用相應(yīng)的方法,進行處理。

其實還有個東西比較重要:事件環(huán)境,在這個環(huán)境中,可以添加事件監(jiān)聽器,可以產(chǎn)生事件,可以觸發(fā)事件監(jiān)聽器。

這個和觀察者模式大同小異,但要比觀察者模式復雜一些。一些邏輯需要手動實現(xiàn),比如注冊監(jiān)聽器,刪除監(jiān)聽器,獲取監(jiān)聽器數(shù)量等等,這里的eventObject也是你自己實現(xiàn)的。

下面我們看下Java中事件機制的實現(xiàn),理解下面的類結(jié)構(gòu)將幫助你Tomcat中監(jiān)聽機制的實現(xiàn)。

  • 監(jiān)聽器
public interface EventListener extends java.util.EventListener {
    void handleEvent(EventObject event);
}
  • 監(jiān)聽事件
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 {
    //監(jiān)聽器列表,監(jiān)聽器的注冊則加入此列表
    private Vector<EventListener> ListenerList = new Vector<>();
    //注冊監(jiān)聽器
    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,事件監(jiān)聽器,
      對open事件感興趣的listener將會執(zhí)行
      **/
    eventSource.notifyListenerEvents(new EventObject("openWindows"));
}

Tomcat中監(jiān)聽機制(Server部分)

基于上面的事件監(jiān)聽的代碼結(jié)構(gòu),你就能知道Tomcat中事件監(jiān)聽的類結(jié)構(gòu)了。

  • 首先要定義一個監(jiān)聽器,它有一個監(jiān)聽方法,用來接受一個監(jiān)聽事件
public interface LifecycleListener {
    /**
     * Acknowledge the occurrence of the specified event.
     *
     * @param event LifecycleEvent that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event);
}
  • 監(jiān)聽事件, 由于它是lifecycle的監(jiān)聽器,所以它握有一個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;
    }
}
  • 事件源的接口和實現(xiàn)

事件源的接口:在Lifecycle中

public interface Lifecycle {
    /** 第1類:針對監(jiān)聽器 **/
    // 添加監(jiān)聽器
    public void addLifecycleListener(LifecycleListener listener);
    // 獲取所以監(jiān)聽器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某個監(jiān)聽器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}

事件源的實現(xiàn): 在 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);
    }
}
  • 接下來是調(diào)用了

比如在LifecycleBase, 停止方法是基于LifecycleState狀態(tài)改變來觸發(fā)上面的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();
        }
    }
}

到此這篇關(guān)于Tomcat的事件監(jiān)聽機制:觀察者模式詳解的文章就介紹到這了,更多相關(guān)Tomcat事件監(jiān)聽機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計

    Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計

    文章詳細介紹了Apache Tomcat Maven Plugin中的部署和卸載功能,通過多層抽象、組合復用和注解驅(qū)動的設(shè)計,實現(xiàn)了靈活、可配置的遠程Tomcat操作,通過代碼展示了Apache Tomcat Maven Plugin(如 tomcat8-maven-plugin)中部署和卸載類目標的設(shè)計體系,感興趣的朋友一起看看吧
    2026-02-02
  • 解析Tomcat的啟動腳本--catalina.bat

    解析Tomcat的啟動腳本--catalina.bat

    本文主要對Tomcat的三個最重要的啟動腳本之一--catalina.bat腳本做了詳細分析,具有很好的參考價值,需要的朋友可以看下
    2016-12-12
  • Tomcat報錯: JDBC unregister 解決辦法

    Tomcat報錯: JDBC unregister 解決辦法

    這篇文章主要介紹了Tomcat報錯: JDBC unregister 解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Tomcat與JDK版本對應(yīng)關(guān)系以及Tomcat各版本特性

    Tomcat與JDK版本對應(yīng)關(guān)系以及Tomcat各版本特性

    這篇文章主要介紹了Tomcat與JDK版本對應(yīng)關(guān)系以及Tomcat各版本特性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • Tomcat配置及如何在Eclipse中啟動

    Tomcat配置及如何在Eclipse中啟動

    這篇文章主要介紹了Tomcat配置及如何在Eclipse中啟動,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • IDEA中Smart?Tomcat插件使用教程

    IDEA中Smart?Tomcat插件使用教程

    本文主要介紹了IDEA中Smart?Tomcat插件使用教程,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-06-06
  • tomcat組件圖解 一個web服務(wù)器的架構(gòu)演化史

    tomcat組件圖解 一個web服務(wù)器的架構(gòu)演化史

    這篇文章主要介紹了tomcat組件圖解 一個web服務(wù)器的架構(gòu)演化史,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • Tomcat將配置文件放在外部的解決方法

    Tomcat將配置文件放在外部的解決方法

    這篇文章主要給大家介紹了關(guān)于Tomcat將配置文件放在外部的相關(guān)資料,對平時工作來說還是挺實用的,需要的朋友們下面隨著小編一起來看看吧
    2021-05-05
  • Eclipse部署Tomcat實現(xiàn)JSP運行的超詳細教程

    Eclipse部署Tomcat實現(xiàn)JSP運行的超詳細教程

    這篇文章主要介紹了Eclipse部署Tomcat實現(xiàn)JSP運行,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • Tomcat開啟JMX服務(wù)方法介紹

    Tomcat開啟JMX服務(wù)方法介紹

    這篇文章主要介紹了Tomcat開啟JMX服務(wù)方法的相關(guān)內(nèi)容,小編覺得挺不錯的,在這里給大家分享一下,需要的朋友可以參考。
    2017-10-10

最新評論

清新县| 甘泉县| 乌什县| 玛沁县| 大新县| 武平县| 高密市| 西峡县| 兴义市| 温泉县| 东丰县| 庄浪县| 顺平县| 达日县| 兴和县| 孟村| 湟源县| 屏东市| 铜梁县| 长寿区| 济南市| 台湾省| 蕉岭县| 军事| 正安县| 微山县| 乌鲁木齐市| 淄博市| 汉源县| 通城县| 宁夏| 剑川县| 娱乐| 大连市| 高雄市| 安西县| 涪陵区| 宜丰县| 彩票| 蒲江县| 盘山县|