摘要:準備好了我們可以開始向中發(fā)布,當發(fā)布后,所有在中的都會收到對應的。將類注入到的中。測試和通過方法將發(fā)布到應用上下文中,同時這個動作會觸發(fā)收到事件。深入剖析發(fā)布與監(jiān)聽的過程在使用方法發(fā)布的時候,最終會調用到中的類的如下的一段代碼。
本篇主要來聊一聊spring中ApplicationListener接口和ApplicationEvent類。
從命名上可以很容易的看出來一個是listener另一個是被監(jiān)聽的事件,但是spring是如何做到listener去監(jiān)聽event?同時我們該如何在日常開發(fā)過程中使用spring為我們提供的這一個監(jiān)聽模式?
0x01 listener和event關系spring啟動后會為我們創(chuàng)建好一個上下文,也即是我們經(jīng)常聽到的spring IOC的上下文ApplicationContext,可以理解ApplicationContext中是初始化了所有在.xml文件配置的bean標簽的bean。
我們通過在.xml文件中定義一個listener的bean,這個listener用來監(jiān)聽event,listener通過實現(xiàn)方法com.boyu.budmw.test.AppListener#onApplicationEvent來對event進行處理。
listener準備好了我們可以開始向ApplicationContext中發(fā)布event,當event發(fā)布后,所有在ApplicationContext中的listener都會收到對應的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ù)的構造函數(shù),因為父類ApplicationEvent中沒有默認的構造方法,所以子類必須重載構造函數(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進行處理了。
將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應用上下文中,同時這個動作會觸發(fā)listener收到event事件。
0x03 深入剖析發(fā)布與監(jiān)聽的過程在使用org.springframework.context.ApplicationEventPublisher#publishEvent方法發(fā)布event的時候,最終會調用到spring中的org.springframework.context.event.SimpleApplicationEventMulticaster類的如下的一段代碼。
當然這也是取決于你有沒有對applicationEventMulticaster進行定制,如果定制了,會走到你自己定制的邏輯,下面這段是spring默認的一段邏輯。
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,然后依次調用各個listener。
getApplicationListeners這個方法中的邏輯是從beanFactory中獲取所有的ApplicationListener對象。
0x04 這個特性有什么用?當然這里也只能談談自己認識到的應用場景,event中可以定義一些復雜的對象或者叫服務,這樣服務提供者就和服務的使用者徹底解耦了。
根據(jù)自己的業(yè)務場景可以做很多事情,期待你的補充。
0x05 參考這篇我想最有參考價值的東西還是spring的源碼,可以去調試相關的代碼。spring有很多有價值或者說值得學習的設計思想,同樣編碼的規(guī)范也可以讓你學到很多,多多跟著自己的思維去調試spring源碼。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/66004.html
摘要:實體代碼如下所示恒宇少年碼云用戶名密碼創(chuàng)建內添加一個注冊方法,該方法只是實現(xiàn)注冊事件發(fā)布功能,代碼如下所示恒宇少年碼云用戶注冊方法省略其他邏輯發(fā)布事件事件發(fā)布是由對象管控的,我們發(fā)布事件前需要注入對象調用方法完成事件發(fā)布。 ApplicationEvent以及Listener是Spring為我們提供的一個事件監(jiān)聽、訂閱的實現(xiàn),內部實現(xiàn)原理是觀察者設計模式,設計初衷也是為了系統(tǒng)業(yè)務邏輯之...
摘要:前言由于之前使用事件機制出現(xiàn)了問題,所以特意去了解這塊的源碼。事件機制其實就是事件發(fā)布訂閱注意在中訂閱指的是監(jiān)聽。 前言 由于之前使用Spring事件機制出現(xiàn)了問題,所以特意去了解這塊的源碼。Spring事件機制其實就是事件發(fā)布/訂閱(注意在Spring中訂閱指的是監(jiān)聽)。 PS:Spring版本為5.1.5.RELEASE 源碼分析 初始化 初始化這塊關鍵是核心組件的注冊 App...
摘要:背景是事件機制的一部分,與抽象類類配合來完成的事件機制。如果容器中存在的,當調用方法時,對應的會被觸發(fā)。單元測試類執(zhí)行單元測試,會發(fā)現(xiàn)事件發(fā)布之后,監(jiān)聽器方法被調用,日志被打印出來。 背景 ApplicationListener是Spring事件機制的一部分,與抽象類ApplicationEvent類配合來完成ApplicationContext的事件機制。 如果容器中存在Applic...
摘要:前言之前使用的事件機制來改造系統(tǒng),完成了部分模塊的解耦。但是實際使用時卻發(fā)現(xiàn)存在以下問題當批量推送時,如果在處理的過程中拋出異常,則會導致后續(xù)的推送中斷。但是實際上卻是拋出異常會導致后續(xù)事件的推送中斷。 前言 之前使用Spring的事件機制來改造系統(tǒng),完成了部分模塊的解耦。但是實際使用時卻發(fā)現(xiàn)存在以下問題: 當ApplicationEventPublisher批量推送Applicati...
摘要:會一直完善下去,歡迎建議和指導,同時也歡迎中用到了那些設計模式中用到了那些設計模式這兩個問題,在面試中比較常見。工廠設計模式使用工廠模式可以通過或創(chuàng)建對象。 我自己總結的Java學習的系統(tǒng)知識點以及面試問題,已經(jīng)開源,目前已經(jīng) 41k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...
閱讀 3235·2021-11-11 16:55
閱讀 2507·2021-10-13 09:39
閱讀 2429·2021-09-13 10:27
閱讀 2165·2019-08-30 15:55
閱讀 3094·2019-08-30 15:54
閱讀 3139·2019-08-29 16:34
閱讀 1833·2019-08-29 12:41
閱讀 1075·2019-08-29 11:33