目錄結構java
以前講了深刻Spring Events事件驅動模型,發現一些小夥伴不知足於僅僅會用,還對事件驅動(Event Driven)的原理很感興趣,所以咱們這篇文章就帶你們看下Spring事件驅動的核心源碼。設計模式
對於事件驅動,你能夠跟生活中的實際場景聯繫一下,就很容易理解了。併發
好比你去賓館開房,次日早上6點要去趕飛機,就打電話給前臺,前臺記錄了你的房間號和叫醒時間,次日早上,前臺就在指定的時間挨個給須要叫醒的顧客打電話,叫他們起牀。異步
在這個故事裏,你就是一個監聽器,前臺就是一個廣播器,而早上6點提供叫醒服務就是一個事件。當這些早上六點被叫醒的監聽器們起牀之後,有的去了機場,有的去了火車站,這就是對同一個事件不一樣的監聽器進行了不一樣的邏輯處理。ide
你只要記住事件驅動中的三個角色,就很容易理解事件驅動的本質了,它們分別是:事件監聽器、事件廣播器和事件。post
咱們的事件監聽器都實現了ApplicationListener
接口,這個接口中只有一個方法void onApplicationEvent(E event)
,用於處理監聽到的事件。至於監聽到事件之後怎麼辦,就是你的自由發揮餘地了。spa
Spring經過事件廣播器ApplicationEventMulticaster
接口將事件分配給專門的監聽器。線程
ApplicationEventMulticaster
接口定義了3種方法:設計
void addApplicationListener(ApplicationListener<?> var1);
void addApplicationListenerBean(String var1);
複製代碼
void removeApplicationListener(ApplicationListener<?> var1);
void removeApplicationListenerBean(String var1);
void removeAllListeners();
複製代碼
void multicastEvent(ApplicationEvent var1);
void multicastEvent(ApplicationEvent var1, @Nullable ResolvableType var2);
複製代碼
AbstractApplicationEventMulticaster
實現了基本的添加和刪除監聽器的方法。code
在實現類SimpleApplicationEventMulticaster
的源碼裏,你能夠看到事件是被ApplicationEventMulticaster
的multicastEvent(ApplicationEvent event)
方法發送到每一個已註冊的監聽器的。
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//根據eventType獲取全部該類型事件已註冊的監聽器集合並遍歷
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
//獲取線程池
Executor executor = getTaskExecutor();
if (executor != null) {
//若是有線程池則併發觸發監聽器的方法
executor.execute(() -> invokeListener(listener, event));
}
else {
//沒有線程池則依次執行
invokeListener(listener, event);
}
}
}
複製代碼
到這裏你應該明白SpringEvents事件驅動的原理了:
以Spring容器爲基礎,經過一個集合保存事件與事件監聽器之間的對應關係(想一想以前講的發佈者/訂閱者),而後當發佈事件的時候,根據事件類型獲取該事件全部的訂閱者,最後經過同步或異步的方式通知到每一個監聽器並執行監聽方法。
So easy !