Spring注解驅(qū)動之@EventListener注解使用方式
概述
之前我們說過可以通過實(shí)現(xiàn)ApplicationListener接口來監(jiān)聽處理事件。
其實(shí)還有一種注解方式來監(jiān)聽處理事件。即使用@EventListener注解,通過該注解就可以在方法上監(jiān)聽事件了。
這樣普通的業(yè)務(wù)邏輯組件中就可以直接使用這個(gè)注解來監(jiān)聽事件了,無需實(shí)現(xiàn)ApplicationListener接口了,確實(shí)比較方便,但是其原理是和ApplicationListener接口一樣的,也可以自定義一個(gè)多波器實(shí)現(xiàn)異步監(jiān)聽事件,定義方法與之前一致。Spring注解驅(qū)動之ApplicationListener異步處理事件
@EventListener注解的用法
首先,編寫一個(gè)普通的業(yè)務(wù)邏輯組件,例如UserService,并在該組件上標(biāo)注一個(gè)@Service注解。
我們只需要簡單的在該方法上標(biāo)注一個(gè)@EventListener注解,就可以讓方法來監(jiān)聽事件了??梢酝ㄟ^注解的classes屬性來指定需要監(jiān)聽的事件。
例如,我們可以讓listen方法監(jiān)聽ApplicationEvent及其子事件。
最后我們在參數(shù)的位置上寫一個(gè)ApplicationEvent參數(shù)來接收事件,參數(shù)值是在Spring框架調(diào)用的時(shí)候自動賦值的。
package com.meimeixia.ext; import org.springframework.context.ApplicationEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @Service public class UserService { // 一些其他的方法... @EventListener(classes=ApplicationEvent.class) public void listen(ApplicationEvent event) { System.out.println("UserService...監(jiān)聽到的事件:" + event); } }
寫個(gè)測試用例。
package com.meimeixia.test; import org.junit.Test; import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.meimeixia.ext.ExtConfig; public class IOCTest_Ext { @Test public void test01() { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class); // 發(fā)布一個(gè)事件 applicationContext.publishEvent(new ApplicationEvent(new String("我發(fā)布的事件")) { }); // 關(guān)閉容器 applicationContext.close(); } }
你會發(fā)現(xiàn)Eclipse控制臺打印出了如下內(nèi)容,可以清晰地看到,不僅我們之前編寫的監(jiān)聽器(例如MyApplicationListener)收到了事件,而且UserService組件也收到了事件。
也就是說,每一個(gè)都能正確地收到事件。
@EventListener注解的原理
我們可以點(diǎn)進(jìn)去@EventListener這個(gè)注解里面去看一看,如下圖所示,可以看到這個(gè)注解上面有一大堆的描述,從描述中我們可以猜到這個(gè)注解的內(nèi)部工作原理。
描述中有一個(gè)醒目的字眼,即參考EventListenerMethodProcessor。意思可能是說,如果你想搞清楚@EventListener注解的內(nèi)部工作原理,那么可以參考EventListenerMethodProcessor這個(gè)類。
EventListenerMethodProcessor是一個(gè)處理器,其作用是來解析方法上的@EventListener注解的。
這也就是說,Spring會使用EventListenerMethodProcessor來解析方法上的@EventListener注解。
因此,搞清楚這個(gè)處理器是怎樣工作的,就搞清楚了@EventListener注解的內(nèi)部工作原理。
仔細(xì)看一下SmartInitializingSingleton接口中afterSingletonsInstantiated方法上面的描述信息,不難看出該方法是在所有的單實(shí)例bean已經(jīng)全部被創(chuàng)建完了以后才會被執(zhí)行。
在介紹SmartInitializingSingleton接口的時(shí)候,我們也能從描述信息中知道,在所有的單實(shí)例bean已經(jīng)全部被創(chuàng)建完成以后才會觸發(fā)該接口。緊接著下面一段的描述還說了,該接口的調(diào)用時(shí)機(jī)有點(diǎn)類似于ContextRefreshedEvent事件,即在容器刷新完成以后,便會回調(diào)該接口。也就是說,這個(gè)時(shí)候容器已經(jīng)創(chuàng)建完了。
如果所有的單實(shí)例bean都已經(jīng)創(chuàng)建完了,也就是說下面這一步都執(zhí)行完了,那么說明IOC容器已經(jīng)創(chuàng)建完成了。
緊接著便會來調(diào)用finishRefresh方法,容器已經(jīng)創(chuàng)建完了,此時(shí)就會來發(fā)布容器已經(jīng)刷新完成的事件。
這就呼應(yīng)了開頭的那句話,即SmartInitializingSingleton接口的調(diào)用時(shí)機(jī)有點(diǎn)類似于ContextRefreshedEvent事件,即在容器刷新完成以后,便會回調(diào)該接口。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot2.0 中 HikariCP 數(shù)據(jù)庫連接池原理解析
這篇文章主要介紹了SpringBoot2.0 中 HikariCP 數(shù)據(jù)庫連接池原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01java.lang.UnsupportedOperationException分析及解決辦法
日常開發(fā)中我遇到j(luò)ava.lang.UnsupportedOperationException:異常兩次了,下面這篇文章主要給對大家介紹了關(guān)于java.lang.UnsupportedOperationException分析及解決辦法,需要的朋友可以參考下2024-03-03Java如何發(fā)起http請求的實(shí)現(xiàn)(GET/POST)
這篇文章主要介紹了Java如何發(fā)起http請求的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03SpringBoot如何使用@Value取配置文件中的map配置
這篇文章主要介紹了SpringBoot如何使用@Value取配置文件中的map配置方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說明
這篇文章主要介紹了Java形參和實(shí)參的實(shí)例之Integer類型與Int類型用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10