居然可以這樣監聽,你學會了嗎?
?前面講到要使自定義注解生效需要寫一段驅動代碼,那驅動代碼什么開始執行比較合適呢?大家可能知道答案:應用啟動的時候。
回到具體的代碼實現中,假設應用程序(客戶端或服務端)依賴了 RPC框架并且使用了Spring?環境,對Spring?比較熟悉的小伙伴應該知道,Spring?在啟動的過程中會初始化bean?,那是不是可以在初始化bean之后去執行這段驅動代碼呢?答案是肯定的。
查閱相關資料后,Spring 監聽器可以實現上面這個訴求。
Spring 監聽器
監聽器在使用過程中可以監聽某些感興趣的事件,監聽到事件來臨時可以做出響應處理。
Spring事件監聽體系包括三大核心組件:事件監聽器、事件、事件廣播器,如下圖:
Spring 監聽器
事件廣播器
事件廣播器或者叫事件多播器負責廣播發生的事件并通知所有監聽器,所有的事件監聽器都會提前注冊在事件廣播器中。
事件
所有的動作都可能被定義為一個事件,事件發生后事件廣播器通知所有的監聽器,監聽器根據情況做出響應。
Spring 定義了一個事件基類:ApplicationEvent,看一下源碼:
ApplicationEvent? 繼承 JDK 定義的事件基類:EventObject,
ApplicationEvent 是一個抽象類,如果需要自定義事件需要繼承這個類:
當然 Spring 自身已經定義了非常多的事件:
- ContextRefreshedEvent:ApplicationContext 被初始化或刷新時,該事件被發布。初始化是指所有的Bean被成功裝載,后處理Bean被檢測并激活,所有Singleton Bean 被預實例化,ApplicationContext容器已就緒可用。
- ContextStartedEvent:ApplicationContext 啟動后,該事件被發布。
- ContextStoppedEvent:ApplicationContext 停止后,該事件被發布。
- ContextClosedEvent:ApplicationContext 關閉后,該事件被發布。
以上僅僅列舉了幾個常用的 Spring 事件。
根據前面分析的業務訴求,我們期望所有的bean?初始化完之后開始執行自定義注解的驅動代碼,所以ContextRefreshedEvent這個事件才是我們感興趣的,看一下源碼:
看起來非常簡單,繼承了ApplicationContextEvent?,繼續跟一下源碼可以發現ApplicationContextEvent?繼承了我們上面講的ApplicationEvent。
事件監聽器
所有的事件監聽器都注冊在事件廣播器中,這好比觀察者模式中的觀察者。
在 Spring 中ApplicationListener?是事件監聽器的頂層接口,繼承自 JDK 的EventListener,所有的監聽器都必須實現這個接口。
定義了一個onApplicationEvent方法,當有感興趣的事件發生后就會執行這個方法進行處理。
實現自定義監聽器
上面介紹了 Spring 監聽體系的一些基礎知識,并通過一些源碼進行輔助介紹,這些代碼都不是 RPC 框架要寫的,RPC 框架當前要做的是實現一個自定義監聽器監聽感興趣的事件。
通過結合業務訴求分析出:自定義一個監聽器用來監聽 Spring 內置ContextRefreshedEvent事件。
自定義的監聽器實現了ApplicationListener?接口,并重寫onApplicationEvent方法,方法中待實現的業務邏輯是重中之重。
待實現的業務邏輯中需要對@ServiceExpose和@ServiceReference?這兩個注解進行處理,@ServiceExpose?對應服務端,@ServiceReference對應客戶端,所以基本就是兩大塊:服務端邏輯處理和客戶端邏輯處理。
注意一下,文中提到的服務端或客戶端是站在功能角度上看的,不能片面理解,一個應用程序(服務或微服務)既可能是服務端也可能是客戶端:
Spring 監聽器-第 2 頁
如上圖,微服務 A 調用微服務 B,微服務 B 又調用微服務 C,微服務 B 在整個調用鏈中既是客戶端又是服務端。
代碼結構
自定義監聽器DefaultRpcListener放在 listener 包下,目前 RPC 框架代碼工程結構如下:
小結
本小節首先學習了Spring 監聽的基本機制,了解到監聽體系有三大關鍵要素:事件監聽器、事件、事件廣播器,事件監聽器會提前注冊到事件廣播器中,當感興趣的事件發生后事件廣播器會通知到事件監聽器,這樣事件監聽器就可以根據業務場景進行響應。
Spring 提供了事件的基類,大家可以自定義事件,當然也可以直接使用 Spring 內置的事件,結合 RPC 框架的業務特點我們發現ContextRefreshedEvent事件比較符合我們的訴求。
Spring 定義了事件監聽器ApplicationListener?頂層接口,我們只需要實現該接口就可以自定義一個監聽器,在監聽器中重寫onApplicationEvent方法實現相應的業務邏輯。
自定義監聽器主要的業務邏輯包括兩大塊:服務端和客戶端,服務端邏輯主要處理@ServiceExpose?注解,客戶端邏輯主要處理@ServiceReferece注解。關于注解處理的邏輯我們下一小節詳細講解。