新聞中心
?前面講到要使自定義注解生效需要寫一段驅(qū)動代碼,那驅(qū)動代碼什么開始執(zhí)行比較合適呢?大家可能知道答案:應(yīng)用啟動的時候。

創(chuàng)新互聯(lián)公司主打移動網(wǎng)站、成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)站改版、網(wǎng)絡(luò)推廣、網(wǎng)站維護、申請域名、等互聯(lián)網(wǎng)信息服務(wù),為各行業(yè)提供服務(wù)。在技術(shù)實力的保障下,我們?yōu)榭蛻舫兄Z穩(wěn)定,放心的服務(wù),根據(jù)網(wǎng)站的內(nèi)容與功能再決定采用什么樣的設(shè)計。最后,要實現(xiàn)符合網(wǎng)站需求的內(nèi)容、功能與設(shè)計,我們還會規(guī)劃穩(wěn)定安全的技術(shù)方案做保障。
回到具體的代碼實現(xiàn)中,假設(shè)應(yīng)用程序(客戶端或服務(wù)端)依賴了 RPC框架并且使用了Spring?環(huán)境,對Spring?比較熟悉的小伙伴應(yīng)該知道,Spring?在啟動的過程中會初始化bean?,那是不是可以在初始化bean之后去執(zhí)行這段驅(qū)動代碼呢?答案是肯定的。
查閱相關(guān)資料后,Spring 監(jiān)聽器可以實現(xiàn)上面這個訴求。
Spring 監(jiān)聽器
監(jiān)聽器在使用過程中可以監(jiān)聽某些感興趣的事件,監(jiān)聽到事件來臨時可以做出響應(yīng)處理。
Spring事件監(jiān)聽體系包括三大核心組件:事件監(jiān)聽器、事件、事件廣播器,如下圖:
Spring 監(jiān)聽器
事件廣播器
事件廣播器或者叫事件多播器負(fù)責(zé)廣播發(fā)生的事件并通知所有監(jiān)聽器,所有的事件監(jiān)聽器都會提前注冊在事件廣播器中。
事件
所有的動作都可能被定義為一個事件,事件發(fā)生后事件廣播器通知所有的監(jiān)聽器,監(jiān)聽器根據(jù)情況做出響應(yīng)。
Spring 定義了一個事件基類:ApplicationEvent,看一下源碼:
public abstract class ApplicationEvent extends EventObject {
/** 事件發(fā)生的時間 */
private final long timestamp;
/**
* 創(chuàng)建一個實例
* @param source 事件來源
*/
public ApplicationEvent(Object source){
super(source);
this.timestamp = System.currentTimeMillis();
}
……省略其他代碼
}ApplicationEvent? 繼承 JDK 定義的事件基類:EventObject,
public class EventObject implements java.io.Serializable {
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
……省略其他代碼
}ApplicationEvent 是一個抽象類,如果需要自定義事件需要繼承這個類:
public class MyEvent extends ApplicationEvent {
……省略其他代碼
}當(dāng)然 Spring 自身已經(jīng)定義了非常多的事件:
- ContextRefreshedEvent:ApplicationContext 被初始化或刷新時,該事件被發(fā)布。初始化是指所有的Bean被成功裝載,后處理Bean被檢測并激活,所有Singleton Bean 被預(yù)實例化,ApplicationContext容器已就緒可用。
- ContextStartedEvent:ApplicationContext 啟動后,該事件被發(fā)布。
- ContextStoppedEvent:ApplicationContext 停止后,該事件被發(fā)布。
- ContextClosedEvent:ApplicationContext 關(guān)閉后,該事件被發(fā)布。
以上僅僅列舉了幾個常用的 Spring 事件。
根據(jù)前面分析的業(yè)務(wù)訴求,我們期望所有的bean?初始化完之后開始執(zhí)行自定義注解的驅(qū)動代碼,所以ContextRefreshedEvent這個事件才是我們感興趣的,看一下源碼:
public class ContextRefreshedEvent extends ApplicationContextEvent {
public ContextRefreshedEvent(ApplicationContext source){
super(source);
}
}看起來非常簡單,繼承了ApplicationContextEvent?,繼續(xù)跟一下源碼可以發(fā)現(xiàn)ApplicationContextEvent?繼承了我們上面講的ApplicationEvent。
事件監(jiān)聽器
所有的事件監(jiān)聽器都注冊在事件廣播器中,這好比觀察者模式中的觀察者。
在 Spring 中ApplicationListener?是事件監(jiān)聽器的頂層接口,繼承自 JDK 的EventListener,所有的監(jiān)聽器都必須實現(xiàn)這個接口。
public interface ApplicationListenerextends EventListener {
/**
* 處理事件
* @param event 待響應(yīng)的事件
*/
void onApplicationEvent(E event);
// ……省略其他代碼
}
定義了一個onApplicationEvent方法,當(dāng)有感興趣的事件發(fā)生后就會執(zhí)行這個方法進行處理。
實現(xiàn)自定義監(jiān)聽器
上面介紹了 Spring 監(jiān)聽體系的一些基礎(chǔ)知識,并通過一些源碼進行輔助介紹,這些代碼都不是 RPC 框架要寫的,RPC 框架當(dāng)前要做的是實現(xiàn)一個自定義監(jiān)聽器監(jiān)聽感興趣的事件。
通過結(jié)合業(yè)務(wù)訴求分析出:自定義一個監(jiān)聽器用來監(jiān)聽 Spring 內(nèi)置ContextRefreshedEvent事件。
public class DefaultRpcListener implements ApplicationListener{
public DefaultRpcListener(){
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event){
// TODO 實現(xiàn)業(yè)務(wù)邏輯
// 1 服務(wù)端邏輯處理
// 2 客戶端邏輯處理
}
}
自定義的監(jiān)聽器實現(xiàn)了ApplicationListener?接口,并重寫onApplicationEvent方法,方法中待實現(xiàn)的業(yè)務(wù)邏輯是重中之重。
待實現(xiàn)的業(yè)務(wù)邏輯中需要對@ServiceExpose和@ServiceReference?這兩個注解進行處理,@ServiceExpose?對應(yīng)服務(wù)端,@ServiceReference對應(yīng)客戶端,所以基本就是兩大塊:服務(wù)端邏輯處理和客戶端邏輯處理。
注意一下,文中提到的服務(wù)端或客戶端是站在功能角度上看的,不能片面理解,一個應(yīng)用程序(服務(wù)或微服務(wù))既可能是服務(wù)端也可能是客戶端:
Spring 監(jiān)聽器-第 2 頁
如上圖,微服務(wù) A 調(diào)用微服務(wù) B,微服務(wù) B 又調(diào)用微服務(wù) C,微服務(wù) B 在整個調(diào)用鏈中既是客戶端又是服務(wù)端。
代碼結(jié)構(gòu)
自定義監(jiān)聽器DefaultRpcListener放在 listener 包下,目前 RPC 框架代碼工程結(jié)構(gòu)如下:
├── easy-rpc-spring-boot-starter
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── leixiaoshuai
│ │ └── easyrpc
│ │ ├── annotation
│ │ │ ├── ServiceExpose.java
│ │ │ └── ServiceReference.java
│ │ └── listener
│ │ └── DefaultRpcListener.java
│ └── resources
└── target
小結(jié)
本小節(jié)首先學(xué)習(xí)了Spring 監(jiān)聽的基本機制,了解到監(jiān)聽體系有三大關(guān)鍵要素:事件監(jiān)聽器、事件、事件廣播器,事件監(jiān)聽器會提前注冊到事件廣播器中,當(dāng)感興趣的事件發(fā)生后事件廣播器會通知到事件監(jiān)聽器,這樣事件監(jiān)聽器就可以根據(jù)業(yè)務(wù)場景進行響應(yīng)。
Spring 提供了事件的基類,大家可以自定義事件,當(dāng)然也可以直接使用 Spring 內(nèi)置的事件,結(jié)合 RPC 框架的業(yè)務(wù)特點我們發(fā)現(xiàn)ContextRefreshedEvent事件比較符合我們的訴求。
Spring 定義了事件監(jiān)聽器ApplicationListener?頂層接口,我們只需要實現(xiàn)該接口就可以自定義一個監(jiān)聽器,在監(jiān)聽器中重寫onApplicationEvent方法實現(xiàn)相應(yīng)的業(yè)務(wù)邏輯。
自定義監(jiān)聽器主要的業(yè)務(wù)邏輯包括兩大塊:服務(wù)端和客戶端,服務(wù)端邏輯主要處理@ServiceExpose?注解,客戶端邏輯主要處理@ServiceReferece注解。關(guān)于注解處理的邏輯我們下一小節(jié)詳細(xì)講解。
分享名稱:居然可以這樣監(jiān)聽,你學(xué)會了嗎?
標(biāo)題URL:http://www.dlmjj.cn/article/ccohjos.html


咨詢
建站咨詢
