設計模式之釋出訂閱模式(5) Spring Events原始碼解析
之前講了深入Spring Events事件驅動模型 ,發現一些小夥伴不滿足於僅僅會用,還對事件驅動(Event Driven)的原理很感興趣,因此我們這篇文章就帶大家看下Spring事件驅動的核心原始碼。
對於事件驅動,你可以跟生活中的實際場景聯絡一下,就很容易理解了。
比如你去賓館開房,第二天早上6點要去趕飛機,就打電話給前臺,前臺記錄了你的房間號和叫醒時間,第二天早上,前臺就在指定的時間挨個給需要叫醒的顧客打電話,叫他們起床。
在這個故事裡,你就是一個監聽器 ,前臺就是一個廣播器 ,而早上6點提供叫醒服務 就是一個事件。當這些早上六點被叫醒的監聽器 們起床以後,有的去了機場,有的去了火車站,這就是對同一個事件不同的監聽器進行了不同的邏輯處理。
事件監聽器原始碼
你只要記住事件驅動中的三個角色,就很容易理解事件驅動的本質了,它們分別是:事件監聽器 、事件廣播器 和事件 。
事件監聽器
我們的事件監聽器
都實現了ApplicationListener
介面,這個介面中只有一個方法void onApplicationEvent(E event)
,用於處理監聽到的事件。至於監聽到事件以後怎麼辦,就是你的自由發揮餘地了。
事件廣播器
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
實現了基本的新增和刪除監聽器的方法。
在實現類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 !