Spring事件監(jiān)聽機(jī)制ApplicationEvent方式
前言
ApplicationEvent
以及 Listener
是Spring為我們提供的一個(gè)事件監(jiān)聽、訂閱的實(shí)現(xiàn),內(nèi)部實(shí)現(xiàn)原理是觀察者設(shè)計(jì)模式,設(shè)計(jì)初衷也是為了系統(tǒng)業(yè)務(wù)邏輯之間的解耦,提高可擴(kuò)展性以及可維護(hù)性。
ApplicationEvent的小demo
ApplicationEvent本身是抽象類,無(wú)法直接實(shí)例化。一般通過(guò)子類繼承ApplicationEvent
public class MyApplicationEvent extends ApplicationEvent { private Student student; public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public MyApplicationEvent(Object source) { super(source); } public MyApplicationEvent(Object source, Student student) { super(source); this.student = student; } }
事件定義好之后,我們注冊(cè)個(gè)事件監(jiān)聽器即可。
實(shí)現(xiàn)ApplicationListener接口注冊(cè)監(jiān)聽器
@Component public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(MyApplicationListener.class); @Override public void onApplicationEvent(MyApplicationEvent myApplicationEvent) { Student student = myApplicationEvent.getStudent(); LOGGER.info("學(xué)生對(duì)象是={}", JSONObject.toJSONString(student)); } }
通過(guò)@EventListener注冊(cè)監(jiān)聽器,ApplicationContext.publishEvent 默認(rèn)是同步操作, 并非發(fā)布后不管的異步操作,發(fā)布事件后需要等 @EventListener 執(zhí)行完。
如果需要開啟異步操作 需要在 @EventListener 上 增加 @Async 注解。
@Component public class AsyncApplicationListener { private static final Logger LOGGER = LoggerFactory.getLogger(AsyncApplicationListener.class); @EventListener @Async public void listener(MyApplicationEvent myApplicationEvent) { Student student = myApplicationEvent.getStudent(); LOGGER.info("通過(guò)@EventListener獲取學(xué)生對(duì)象信息={}", JSONObject.toJSONString(student)); } }
通過(guò)實(shí)現(xiàn)SmartApplicationListener接口注冊(cè)監(jiān)聽器
SmartApplicationListener接口繼承了全局監(jiān)聽ApplicationListener,并且泛型對(duì)象使用的ApplicationEvent來(lái)作為全局監(jiān)聽,可以理解為使用SmartApplicationListener作為監(jiān)聽父接口的實(shí)現(xiàn),監(jiān)聽所有事件發(fā)布。
既然是監(jiān)聽所有的事件發(fā)布,那么SmartApplicationListener接口添加了兩個(gè)方法supportsEventType、supportsSourceType來(lái)作為區(qū)分是否是我們監(jiān)聽的事件,只有這兩個(gè)方法同時(shí)返回true時(shí)才會(huì)執(zhí)行onApplicationEvent方法。
@Component public class MySmartApplicationListener implements SmartApplicationListener { private static final Logger LOGGER = LoggerFactory.getLogger(MySmartApplicationListener.class); @Override public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) { return aClass == MyApplicationEvent.class; } @Override public boolean supportsSourceType(Class<?> sourceType) { return sourceType == ApplicationRunnerTest.class; } @Override public int getOrder() { return 0; } @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { MyApplicationEvent myApplicationEvent = (MyApplicationEvent) applicationEvent; LOGGER.info("通過(guò)MySmartApplicationListener 獲取學(xué)生對(duì)象信息={}", JSONObject.toJSONString(myApplicationEvent.getStudent())); } }
可以看到除了上面的方法,還提供了一個(gè)getOrder方法,這個(gè)方法就可以解決執(zhí)行監(jiān)聽的順序問(wèn)題,return的數(shù)值越小證明優(yōu)先級(jí)越高,執(zhí)行順序越靠前
發(fā)布事件
在Spring的Bean中,注入ApplicationContext ,通過(guò)ApplicationContext 來(lái)進(jìn)行事件發(fā)布
@Autowired private ApplicationContext applicationContext; applicationContext.publishEvent(new MyApplicationEvent(this, new Student("愛琴孩", 18)));
運(yùn)行結(jié)果
2023-01-28 10:38:39.696 YYZX_Study 13540 [ main] INFO c.e.s.s.MySmartApplicationListener 37: 通過(guò)MySmartApplicationListener 獲取學(xué)生對(duì)象信息={"age":18,"name":"愛琴孩"}
2023-01-28 10:38:39.696 YYZX_Study 13540 [ main] INFO c.e.study.service.MyApplicationListener 22: 學(xué)生對(duì)象是={"age":18,"name":"愛琴孩"}
2023-01-28 10:38:39.696 YYZX_Study 13540 [tOrderService-1] INFO c.e.s.service.AsyncApplicationListener 25: 通過(guò)@EventListener獲取學(xué)生對(duì)象信息={"age":18,"name":"愛琴孩"}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(54)
下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你2021-08-08Springboot集成Springbrick實(shí)現(xiàn)動(dòng)態(tài)插件的步驟詳解
這篇文章主要介紹了Springboot集成Springbrick實(shí)現(xiàn)動(dòng)態(tài)插件的詳細(xì)過(guò)程,文中的流程通過(guò)代碼示例介紹的非常詳細(xì),感興趣的同學(xué)可以參考一下2023-06-06面試官:詳細(xì)談?wù)凧ava對(duì)象的4種引用方式
這篇文章主要給大家介紹了java面試官常會(huì)問(wèn)到的,關(guān)于Java對(duì)象的4種引用方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05如何在Maven項(xiàng)目配置pom.xml指定JDK版本和編碼
maven是個(gè)項(xiàng)目管理工具,如果我們不告訴它要使用什么樣的jdk版本編譯,它就會(huì)用maven-compiler-plugin默認(rèn)的jdk版本來(lái)處理,這樣就容易出現(xiàn)版本不匹配的問(wèn)題,這篇文章主要給大家介紹了關(guān)于如何在Maven項(xiàng)目配置pom.xml指定JDK版本和編碼的相關(guān)資料,需要的朋友可以參考下2024-01-01Java?spring?通過(guò)注解方式創(chuàng)建對(duì)象的示例詳解
這篇文章主要介紹了java?spring?通過(guò)注解方式創(chuàng)建對(duì)象,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02