設計模式之釋出訂閱模式(5) Spring Events原始碼解析

西召發表於2019-05-05

設計模式之釋出訂閱模式(5) Spring Events原始碼解析


目錄結構

一個“叫床”的故事

之前講了深入Spring Events事件驅動模型,發現一些小夥伴不滿足於僅僅會用,還對事件驅動(Event Driven)的原理很感興趣,因此我們這篇文章就帶大家看下Spring事件驅動的核心原始碼。

對於事件驅動,你可以跟生活中的實際場景聯絡一下,就很容易理解了。

比如你去賓館開房,第二天早上6點要去趕飛機,就打電話給前臺,前臺記錄了你的房間號和叫醒時間,第二天早上,前臺就在指定的時間挨個給需要叫醒的顧客打電話,叫他們起床。

在這個故事裡,你就是一個監聽器,前臺就是一個廣播器,而早上6點提供叫醒服務就是一個事件。當這些早上六點被叫醒的監聽器們起床以後,有的去了機場,有的去了火車站,這就是對同一個事件不同的監聽器進行了不同的邏輯處理。

事件監聽器原始碼

你只要記住事件驅動中的三個角色,就很容易理解事件驅動的本質了,它們分別是:事件監聽器事件廣播器事件

事件監聽器

我們的事件監聽器都實現了ApplicationListener介面,這個介面中只有一個方法void onApplicationEvent(E event),用於處理監聽到的事件。至於監聽到事件以後怎麼辦,就是你的自由發揮餘地了。

事件廣播器

Spring通過事件廣播器ApplicationEventMulticaster介面將事件分配給專門的監聽器。

ApplicationEventMulticaster介面定義了3種方法:

  1. 新增監聽器:
void addApplicationListener(ApplicationListener<?> var1);

void addApplicationListenerBean(String var1);
複製程式碼
  1. 刪除監聽器:
void removeApplicationListener(ApplicationListener<?> var1);

void removeApplicationListenerBean(String var1);

void removeAllListeners();
複製程式碼
  1. 將事件傳送到已註冊的監聽器:
void multicastEvent(ApplicationEvent var1);

void multicastEvent(ApplicationEvent var1, @Nullable ResolvableType var2);
複製程式碼

AbstractApplicationEventMulticaster實現了基本的新增和刪除監聽器的方法。

在實現類SimpleApplicationEventMulticaster的原始碼裡,你可以看到事件是被ApplicationEventMulticastermulticastEvent(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 !


相關連結

Wechat-westcall

相關文章