Tomcat的事件監(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è)計
文章詳細介紹了Apache Tomcat Maven Plugin中的部署和卸載功能,通過多層抽象、組合復用和注解驅(qū)動的設(shè)計,實現(xiàn)了靈活、可配置的遠程Tomcat操作,通過代碼展示了Apache Tomcat Maven Plugin(如 tomcat8-maven-plugin)中部署和卸載類目標的設(shè)計體系,感興趣的朋友一起看看吧2026-02-02
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各版本特性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11
tomcat組件圖解 一個web服務(wù)器的架構(gòu)演化史
這篇文章主要介紹了tomcat組件圖解 一個web服務(wù)器的架構(gòu)演化史,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-08-08
Eclipse部署Tomcat實現(xiàn)JSP運行的超詳細教程
這篇文章主要介紹了Eclipse部署Tomcat實現(xiàn)JSP運行,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08

