摘要:準(zhǔn)備好了我們可以開始向中發(fā)布,當(dāng)發(fā)布后,所有在中的都會收到對應(yīng)的。將類注入到的中。測試和通過方法將發(fā)布到應(yīng)用上下文中,同時這個動作會觸發(fā)收到事件。深入剖析發(fā)布與監(jiān)聽的過程在使用方法發(fā)布的時候,最終會調(diào)用到中的類的如下的一段代碼。
本篇主要來聊一聊spring中ApplicationListener接口和ApplicationEvent類。
從命名上可以很容易的看出來一個是listener另一個是被監(jiān)聽的事件,但是spring是如何做到listener去監(jiān)聽event?同時我們該如何在日常開發(fā)過程中使用spring為我們提供的這一個監(jiān)聽模式?
0x01 listener和event關(guān)系spring啟動后會為我們創(chuàng)建好一個上下文,也即是我們經(jīng)常聽到的spring IOC的上下文ApplicationContext,可以理解ApplicationContext中是初始化了所有在.xml文件配置的bean標(biāo)簽的bean。
我們通過在.xml文件中定義一個listener的bean,這個listener用來監(jiān)聽event,listener通過實現(xiàn)方法com.boyu.budmw.test.AppListener#onApplicationEvent來對event進(jìn)行處理。
listener準(zhǔn)備好了我們可以開始向ApplicationContext中發(fā)布event,當(dāng)event發(fā)布后,所有在ApplicationContext中的listener都會收到對應(yīng)的event。
0x02 如何使用listener和event這一特性
定義event
首先我們要定義一個event,不然拿什么來觸發(fā)?
public class AppEvent extends ApplicationEvent { public AppEvent(Object source) { super(source); } public void sayHi(){ System.out.println("sayHi"); } }
定義一個event非常簡單,但是需要注意,這里一定要實現(xiàn)帶有一個參數(shù)的構(gòu)造函數(shù),因為父類ApplicationEvent中沒有默認(rèn)的構(gòu)造方法,所以子類必須重載構(gòu)造函數(shù)。
定義listener
public class AppListener implements ApplicationListener { public void onApplicationEvent(ApplicationEvent event) { if(!(event instanceof AppEvent)){ return ; } AppEvent appEvent = (AppEvent)event; appEvent.sayHi(); } }
上面是一個listener的實現(xiàn)類,listener類必須實現(xiàn)ApplicationListener接口,同時要實現(xiàn)接口中的onApplicationEvent方法,這個方法會接收到一個event,然后可以對這個event進(jìn)行處理了。
將listener類注入到spring的ApplicationContext中。
測試listener和event
public class ListenerTest { public static void main (String args[]){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml"); AppEvent appEvent = new AppEvent("appEvent"); applicationContext.publishEvent(appEvent); } }
通過org.springframework.context.ApplicationEventPublisher#publishEvent方法將event發(fā)布到spring應(yīng)用上下文中,同時這個動作會觸發(fā)listener收到event事件。
0x03 深入剖析發(fā)布與監(jiān)聽的過程在使用org.springframework.context.ApplicationEventPublisher#publishEvent方法發(fā)布event的時候,最終會調(diào)用到spring中的org.springframework.context.event.SimpleApplicationEventMulticaster類的如下的一段代碼。
當(dāng)然這也是取決于你有沒有對applicationEventMulticaster進(jìn)行定制,如果定制了,會走到你自己定制的邏輯,下面這段是spring默認(rèn)的一段邏輯。
public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @SuppressWarnings("unchecked") public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
這段代碼一看挺簡單,通過org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent)這個方法獲得applicationContext中所有的listener,然后依次調(diào)用各個listener。
getApplicationListeners這個方法中的邏輯是從beanFactory中獲取所有的ApplicationListener對象。
0x04 這個特性有什么用?當(dāng)然這里也只能談?wù)勛约赫J(rèn)識到的應(yīng)用場景,event中可以定義一些復(fù)雜的對象或者叫服務(wù),這樣服務(wù)提供者就和服務(wù)的使用者徹底解耦了。
根據(jù)自己的業(yè)務(wù)場景可以做很多事情,期待你的補(bǔ)充。
0x05 參考這篇我想最有參考價值的東西還是spring的源碼,可以去調(diào)試相關(guān)的代碼。spring有很多有價值或者說值得學(xué)習(xí)的設(shè)計思想,同樣編碼的規(guī)范也可以讓你學(xué)到很多,多多跟著自己的思維去調(diào)試spring源碼。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66004.html
摘要:實體代碼如下所示恒宇少年碼云用戶名密碼創(chuàng)建內(nèi)添加一個注冊方法,該方法只是實現(xiàn)注冊事件發(fā)布功能,代碼如下所示恒宇少年碼云用戶注冊方法省略其他邏輯發(fā)布事件事件發(fā)布是由對象管控的,我們發(fā)布事件前需要注入對象調(diào)用方法完成事件發(fā)布。 ApplicationEvent以及Listener是Spring為我們提供的一個事件監(jiān)聽、訂閱的實現(xiàn),內(nèi)部實現(xiàn)原理是觀察者設(shè)計模式,設(shè)計初衷也是為了系統(tǒng)業(yè)務(wù)邏輯之...
摘要:前言由于之前使用事件機(jī)制出現(xiàn)了問題,所以特意去了解這塊的源碼。事件機(jī)制其實就是事件發(fā)布訂閱注意在中訂閱指的是監(jiān)聽。 前言 由于之前使用Spring事件機(jī)制出現(xiàn)了問題,所以特意去了解這塊的源碼。Spring事件機(jī)制其實就是事件發(fā)布/訂閱(注意在Spring中訂閱指的是監(jiān)聽)。 PS:Spring版本為5.1.5.RELEASE 源碼分析 初始化 初始化這塊關(guān)鍵是核心組件的注冊 App...
摘要:背景是事件機(jī)制的一部分,與抽象類類配合來完成的事件機(jī)制。如果容器中存在的,當(dāng)調(diào)用方法時,對應(yīng)的會被觸發(fā)。單元測試類執(zhí)行單元測試,會發(fā)現(xiàn)事件發(fā)布之后,監(jiān)聽器方法被調(diào)用,日志被打印出來。 背景 ApplicationListener是Spring事件機(jī)制的一部分,與抽象類ApplicationEvent類配合來完成ApplicationContext的事件機(jī)制。 如果容器中存在Applic...
摘要:前言之前使用的事件機(jī)制來改造系統(tǒng),完成了部分模塊的解耦。但是實際使用時卻發(fā)現(xiàn)存在以下問題當(dāng)批量推送時,如果在處理的過程中拋出異常,則會導(dǎo)致后續(xù)的推送中斷。但是實際上卻是拋出異常會導(dǎo)致后續(xù)事件的推送中斷。 前言 之前使用Spring的事件機(jī)制來改造系統(tǒng),完成了部分模塊的解耦。但是實際使用時卻發(fā)現(xiàn)存在以下問題: 當(dāng)ApplicationEventPublisher批量推送Applicati...
摘要:會一直完善下去,歡迎建議和指導(dǎo),同時也歡迎中用到了那些設(shè)計模式中用到了那些設(shè)計模式這兩個問題,在面試中比較常見。工廠設(shè)計模式使用工廠模式可以通過或創(chuàng)建對象。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識點以及面試問題,已經(jīng)開源,目前已經(jīng) 41k+ Star。會一直完善下去,歡迎建議和指導(dǎo),同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...
閱讀 3229·2021-11-11 16:55
閱讀 2492·2021-10-13 09:39
閱讀 2424·2021-09-13 10:27
閱讀 2163·2019-08-30 15:55
閱讀 3088·2019-08-30 15:54
閱讀 3133·2019-08-29 16:34
閱讀 1827·2019-08-29 12:41
閱讀 1072·2019-08-29 11:33