Spring事件監(jiān)聽(tīng)基本原理與使用詳解
一、簡(jiǎn)介
1、Spring事件監(jiān)聽(tīng)基本原理
Spring的事件監(jiān)聽(tīng)機(jī)制和發(fā)布訂閱機(jī)制是很相似的:發(fā)布了一個(gè)事件后,監(jiān)聽(tīng)該類型事件的所有監(jiān)聽(tīng)器會(huì)觸發(fā)相應(yīng)的處理邏輯。
正如Spring官方文檔上所說(shuō)的,整個(gè)上就是一個(gè)觀察者的模式。那么,我們不妨猜測(cè)下,Spring是如何來(lái)實(shí)現(xiàn)事件發(fā)布監(jiān)聽(tīng)的:底層使用一個(gè)集合存儲(chǔ)了所有的監(jiān)聽(tīng)器,當(dāng)發(fā)布了一個(gè)事件后,遍歷事件監(jiān)聽(tīng)器集合,然后過(guò)濾符合事件類型的監(jiān)聽(tīng)器,最后觸發(fā)相應(yīng)的事件處理邏輯。
2、Spring中事件監(jiān)聽(tīng)的相關(guān)規(guī)范
在Spring中,事件監(jiān)聽(tīng)機(jī)制主要涉及到了一下幾個(gè)關(guān)鍵的規(guī)范(抽象類及接口):ApplicationEvent、ApplicationListener、ApplicationEventPublisher
- ApplicationEvent: Spring的事件是符合jdk的規(guī)范的,這個(gè)抽象類繼承了jdk內(nèi)置的事件規(guī)范類EventObject(即jdk建議所有的事件都繼承EventObject這個(gè)類)。ApplicationEvent是Spring家的事件規(guī)范。所以我們?cè)谧远x事件的時(shí)候,可以繼承與ApplicationEvent,比如,Spring家自己關(guān)于容器上下文事件就又定義了一個(gè)容器上下文的時(shí)間規(guī)范ApplicationContextEvent,它同樣是繼承于ApplicationEvent的,只不過(guò)擴(kuò)充了獲取發(fā)出事件容器的方法;今后,我們同樣可以在繼承于ApplicationEvent的基礎(chǔ)上定義自己的事件規(guī)范。
- ApplicationListener:這是一個(gè)函數(shù)式接口,同樣時(shí)事件監(jiān)聽(tīng)器的規(guī)范,當(dāng)監(jiān)聽(tīng)到自己監(jiān)聽(tīng)的事件類型時(shí)就會(huì)調(diào)用onApplicationEvent方法來(lái)執(zhí)行監(jiān)聽(tīng)邏輯
- ApplicationEventPublisher:這同樣是一個(gè)函數(shù)式接口,定義了事件發(fā)布的規(guī)范,任何的事件發(fā)布器ApplicationEventPublisher都是通過(guò)調(diào)用publishEvent來(lái)進(jìn)行事件的發(fā)布
二、Spring事件監(jiān)聽(tīng)器的使用
1、自定義事件創(chuàng)建
在Spring中,所有的事件需要繼承自ApplicationEvent,自定義事件的不同可以監(jiān)聽(tīng)多個(gè),一個(gè)最基礎(chǔ)的MsgEvent如下
public class MyEvent extends ApplicationEvent { private String msg; // 必須繼承實(shí)現(xiàn) public MyEvent(Object source, String msg) { super(source); this.msg = msg; } @Override public String toString() { return "MyEvent{" + "msg='" + msg + '\'' + '}'; } }
2、自定義監(jiān)聽(tīng)器
2.1 方法介紹
springboot進(jìn)行事件監(jiān)聽(tīng)有四種方式,選擇任意一種即可
- 將監(jiān)聽(tīng)器裝載入spring容器(常用)
- 通過(guò)@EventListener注解實(shí)現(xiàn)事件監(jiān)聽(tīng)(常用)
- 手工向ApplicationContext中添加監(jiān)聽(tīng)器
- 在application.properties中配置監(jiān)聽(tīng)器
2.2 將監(jiān)聽(tīng)器裝載入spring容器
// 裝載入spring容器中 @Slf4j @Component public class MyListener1 implements ApplicationListener<MyEvent> { @Override public void onApplicationEvent(MyEvent event) { // 這里可以自定義自己的方法 log.info(String.format("%s監(jiān)聽(tīng)到事件源:%s.", MyListener1.class.getName(), event.toString())); } }
如果不加@Component注解加入Spring容器,也可以手動(dòng)加入
@SpringBootApplication public class ListenerApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ListenerApplication.class, args); //裝載監(jiān)聽(tīng) context.addApplicationListener(new MyListener1()); } }
也可以通過(guò)配置文application.properties中配置監(jiān)聽(tīng)器:context.listener.classes=com.listener.MyListener1
2.3 @EventListener注解實(shí)現(xiàn)事件監(jiān)聽(tīng)
@Component @Slf4j public class MyListener2{ // 通過(guò)注解的方法 @EventListener(MyEvent.class) public void consumer(MyEvent msgEvent) { log.info(String.format("%s監(jiān)聽(tīng)到事件源:%s.", MsgPublisher.class.getName(), msgEvent.toString())); } }
3、事件發(fā)布
前面是消費(fèi)事件,消費(fèi)的前提是有事件產(chǎn)生,在Spring中,發(fā)布事件主要需要借助ApplicationContext來(lái)實(shí)現(xiàn)
@Component @Slf4j public class MsgPublisher implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } // 發(fā)起事件通知 public void publish(String msg) { applicationContext.publishEvent(new MyEvent1(this, msg)); } // 通過(guò)注解的方法 @EventListener(MyEvent.class) public void consumer(MyEvent msgEvent) { log.info(String.format("%s監(jiān)聽(tīng)到事件源:%s.", MsgPublisher.class.getName(), msgEvent.toString())); } /** * 這個(gè)只是測(cè)試,到時(shí)候spring直接調(diào)用即可 */ public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(MsgPublisher.class); MsgPublisher msgPublisher = context.getBean(MsgPublisher.class); msgPublisher.publish("hello world"); } }
到此這篇關(guān)于Spring事件監(jiān)聽(tīng)基本原理與使用詳解的文章就介紹到這了,更多相關(guān)Spring事件監(jiān)聽(tīng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot高級(jí)教程之使用Redis實(shí)現(xiàn)session共享
這篇文章主要為大家詳細(xì)介紹了Spring Boot高級(jí)教程之使用Redis實(shí)現(xiàn)session共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10mybatis-plus 實(shí)現(xiàn)分頁(yè)查詢的示例代碼
本文介紹了在MyBatis-Plus中實(shí)現(xiàn)分頁(yè)查詢,包括引入依賴、配置分頁(yè)插件、使用分頁(yè)查詢以及在控制器中調(diào)用分頁(yè)查詢的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11IntelliJ IDEA安裝scala插件并創(chuàng)建scala工程的步驟詳細(xì)教程
這篇文章主要介紹了IntelliJ IDEA安裝scala插件并創(chuàng)建scala工程的步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Mybatis-Plus自動(dòng)生成代碼的實(shí)現(xiàn)示例
在工作中,程序員很多時(shí)候都是在寫類似的代碼,可以使用自動(dòng)生成代碼,本文主要介紹了Mybatis-Plus自動(dòng)生成代碼的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11Java實(shí)現(xiàn)多項(xiàng)式除法的代碼示例
今天小編就為大家分享一篇關(guān)于Java實(shí)現(xiàn)多項(xiàng)式除法的代碼示例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10java創(chuàng)建二維碼并賦予url鏈接的功能實(shí)現(xiàn)
這篇文章給大家分享java創(chuàng)建二維碼并賦予url鏈接的功能實(shí)現(xiàn),需要獲取要賦值給二維碼的鏈接后綴,通過(guò)設(shè)置二維碼的訪問(wèn)路徑等一系列操作,具體實(shí)現(xiàn)代碼跟隨小編一起看看吧2021-06-06spring boot 日志/頁(yè)面處理、實(shí)體類構(gòu)建、后臺(tái)管理功能的實(shí)現(xiàn)
這篇文章主要介紹了spring boot 日志/頁(yè)面處理、實(shí)體類構(gòu)建、后臺(tái)管理功能的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08