Spring事件的觀察者模式

介紹

觀察者模式的本質是“定義對象之間的一對多依賴關系,以便當一個對象改變狀態時,其所有依賴關系都會得到通知并自動更新。” GoF。 觀察者模式是發布/訂閱模式的子集,它允許許多觀察者對象查看事件。

可以在不同的情況下使用此模式,但總而言之,可以說觀察者模式可以在對象應該能夠將消息通知其他對象并且您不希望這些對象緊密耦合時應用。 就我而言,當異步事件應通知一個或多個圖形組件時,我使用了這種模式。

可以使用臨時解決方案或使用java.util.Observer/Observable類來實現此模式。 但是我的項目總是用Spring開發的,無論是Web還是桌面應用 。 因此,在當前文章中,我將解釋如何使用Spring實現Observer模式。

手扶

Spring ApplicationContext中的事件處理是通過ApplicationEvent類和ApplicationListener接口提供的。 如果將實現ApplicationListener接口的bean部署到上下文中,則每次將ApplicationEvent發布到容器時, ApplicationListener都會接收到它。
Spring帶有內置事件,例如ContextStartedEventContextStoppedEvent ,但是您也可以創建自己的自定義事件。

為了開發自己的事件,需要三個類, 觀察者角色, 可觀察角色和事件觀察者是那些接收事件并且必須實現ApplicationListener類的人。 可觀察類負責發布事件,并且必須實現ApplicationEventPublisherAware 。 最后, 事件類必須擴展ApplicationEvent

編碼

我要實現的是Observer模式的Wikipedia示例( http://en.wikipedia.org/wiki/Observer_pattern#Example ),但是使用Spring Events而不是Observer / Observable Java類。 該示例是一個基本的發布/訂閱示例,其中一個String消息從一個模塊發送到另一個模塊。
讓我們創建MessageEvent 。 此事件包含一個String,它表示我們要發送的消息。 這是一個從ApplicationEvent擴展的簡單類。

public class MessageEvent extends ApplicationEvent {*** *private static final long serialVersionUID = 5743058377815147529L;private String message;public MessageEvent(Object source, String message) {super(source);this.message = message;}@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append('MessageEvent [message=').append(message).append(']');return builder.toString();}}

下一個類是Observable類。 此類必須實現ApplicationEventPublisherAware 。 此接口使用ApplicationEventPublisher作為參數定義了一個setter方法。 此參數用于發布事件。
在當前的實現中,該代碼還實現了Runnable接口,因此用戶可以從控制臺輸入中進行創建,

public class EventSource implements Runnable, ApplicationEventPublisherAware {private ApplicationEventPublisher applicationEventPublisher = null;public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}public void run() {final InputStreamReader isr = new InputStreamReader(System.in);final BufferedReader br = new BufferedReader(isr);while (true) {try {String response = br.readLine();System.out.println(Thread.currentThread().getName());this.applicationEventPublisher.publishEvent(new MessageEvent(this, response));} catch (IOException e) {e.printStackTrace();}}}}

Observer類甚至更簡單。 實現ApplicationListener接口。 發布事件時將調用onApplicationEvent方法。 看到它是一個通用接口,因此不需要強制轉換。 這不同于java.util.Observer類。

public class ResponseHandler implements ApplicationListener<MessageEvent> {public void onApplicationEvent(MessageEvent messageEvent) {System.out.println(Thread.currentThread().getName());System.out.println(messageEvent);}}

在應用程序上下文文件中,您同時注冊了ApplicationListenerApplicationEventPublisherAware Bean。

最后是一個主類來測試系統。 創建一個線程以執行多個異步事件。

public class MyApp {public static void main(String args[]) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext('classpath:META-INFspringapp-context.xml');EventSource eventSource = applicationContext.getBean('eventSource', EventSource.class);Thread thread = new Thread(eventSource);thread.start();}}

因此,啟動程序并編寫一些內容以進行控制臺。 您將看到類似以下內容:
你好 Thread-0 Thread-0 MessageEvent [message = hello]
我輸入了“ hello ”消息,并打印了事件發布者的線程名 。 然后發送事件并打印處理程序線程名稱 。 最后顯示接收到的事件。 有一件事情應該引起您的注意。 發送者( Observable )和接收者( Observer )都在同一線程中執行; 默認情況下,事件偵聽器同步接收事件。 這意味著publishEvent()方法將阻塞,直到所有偵聽器都已完成對事件的處理為止。 這種方法有很多優點(例如,重用事務上下文等),但是在某些情況下,您希望每個事件都在新線程中執行, Spring也支持此策略。

Spring中 ,負責事件管理的類是SimpleApplicationEventMulticaster 。 此類將所有事件多播到所有注冊的偵聽器,讓偵聽器忽略它們不感興趣的事件。默認行為是在調用線程中調用所有偵聽器。

現在,我將解釋如何初始化Spring Event Architecture以及如何進行修改。 默認情況下,當ApplicationContext 啟動后,它將調用initApplicationEventMulticaster方法。 此方法驗證是否存在與類型ApplicationEventMulticaster的ID applicationEventMulticaster的bean。 如果是這樣,則使用已定義的ApplicationEventMulticaster ,否則,將創建具有默認配置的新SimpleApplicationEventMulticaster

SimpleApplicationEventMulticaster具有可用于指定哪些java.util.concurrent.Executor將執行事件setTaskExecutor。 因此,如果您希望每個事件在不同的線程中執行,那么一個好的方法是使用ThreadPoolExecutor 。 如上一段所述,現在我們必須顯式定義SimpleApplicationEventMulticaster而不是 使用默認的。 讓我們實現:

<beans xmlns='http:www.springframework.orgschemabeans' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns:context='http:www.springframework.orgschemacontext' xmlns:task='http:www.springframework.orgschematask' xsi:schemaLocation='http:www.springframework.orgschematask http:www.springframework.orgschemataskspring-task-3.0.xsd http:www.springframework.orgschemabeans http:www.springframework.orgschemabeansspring-beans-3.0.xsd http:www.springframework.orgschemacontext http:www.springframework.orgschemacontextspring-context-3.0.xsd'><bean id='eventSource' class='org.asotobu.oo.EventSource' > <bean id='responseHandler' class='org.asotobu.oo.ResponseHandler' > <task:executor id='pool' pool-size='10' > <bean id='applicationEventMulticaster'        class='org.springframework.context.event.SimpleApplicationEventMulticaster'><property name='taskExecutor' ref='pool' > <bean><beans>

首先,必須將SimpleApplicationEventMulticaster定義為ID為applicationEventMulticaster的bean。 然后設置任務池,然后我們重新運行主類。 輸出將是:
你好 線程1 池1 MessageEvent [message = hello]
請注意,現在發送方和接收方線程有所不同。

當然,您可以為更復雜的操作創建自己的ApplicationEventMulticaster 。 您只需要實現ApplicationEventMulticaster并使用applicationEventMulticaster bean名稱定義它,事件將根據您自己的策略執行。

希望現在您的Spring桌面應用程序可以充分利用Spring事件來分隔模塊。

下載代碼。

參考:來自JCG合作伙伴 Alex Soto的Spring Events觀察者模式,來自One Jar To Rule All All博客。


翻譯自: https://www.javacodegeeks.com/2012/08/observer-pattern-with-spring-events.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371446.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371446.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371446.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jQuery選擇什么版本 1.x? 2.x? 3.x?

目前jQuery有三個大版本&#xff1a; 1.x&#xff1a;兼容ie678,使用最為廣泛的&#xff0c;官方只做BUG維護&#xff0c;功能不再新增。因此一般項目來說&#xff0c;使用1.x版本就可以了&#xff0c;最終版本&#xff1a;1.12.4 (2016年5月20日)2.x&#xff1a;不兼容ie678&a…

Delta DVP 系列 PLC 各裝置 Modbus 地址

此Modbus地址表以 1 為基礎地址 Device Range Type DVP address (Hex) Modbus address (Dec) Effective ES/EX/SS SA/SX/SC EH S 000~255 bit 0000~00FF 000001~000256 0~127 0~1024 0~1024 S 256~511 bit 0100~01FF 000247~000512 S 512~767 bit 020…

Reporting Service 2008 “報表服務器數據庫內出錯。此錯誤可能是因連接失敗、超時或數據庫中磁盤空間不足而導致的”...

今天遇到了兩個關于Reporting Service的問題&#xff0c; 出現問題的環境為Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64) 。具體情況請見下面描述。 1&#xff1a;在修改報表的訂閱后&#xff0c;保存時出現下面錯誤&#xff1a; 提示&#xff1a;報表服務器數據庫…

Java 7:HashMap與ConcurrentHashMap

從我過去有關性能的文章和HashMap案例研究中可能已經看到&#xff0c;Java線程安全性問題可以很輕松地使Java EE應用程序和Java EE容器崩潰。 在對Java EE性能問題進行故障排除時&#xff0c;我觀察到的最常見問題之一是由非線程安全的HashMap get&#xff08;&#xff09;和pu…

計算機網絡按信息傳輸介質的性能來劃分,大學計算機基礎練習題網絡技術.doc...

網絡技術一、單選&#xff1a;1. 在計算機網絡中&#xff0c;表征數據傳輸可靠性的指標是( )。A?誤碼率 B?頻帶利用率C?信道容量 D?傳輸速率參考答案&#xff1a;A2. 和通信網絡相比&#xff0c;計算機網絡最本質的功能是( )。A?數據通信 B?資源共享C?提高計算機的可靠性…

【2017-03-02】集合、結構體、枚舉

集合和數組的差別&#xff1a; 數組&#xff1a;同一類型&#xff0c;固定長度集合&#xff1a;不同類型&#xff0c;不固定長度 一、普通集合&#xff08;弱類型&#xff09; 1、ArryList 使用集合首先要引用命名空間。 或者在ArryList上右鍵找“解析”。 2、集合的定義&#…

Hibernate懶/急加載示例

這篇文章將重點討論為什么以及如何在應用程序中使用稱為LAZY和EAGER加載的概念&#xff0c;以及如何使用Spring的休眠模板以EAGER方式加載LAZY實體。 當然&#xff0c;正如標題本身所暗示的那樣&#xff0c;我們將通過一個示例來說明這一點。 場景就是這樣&#xff1b; 您是一…

讀者使用計算機終端是指,全國2010年10月自學考試管理系統中計算機應用真題及答案...

A.上級模塊向下級模塊傳遞控制信號B.下級模塊對上級模塊傳遞控制信號C.同級模塊之間傳遞數據或控制信號D.上級模塊向下級模塊傳遞數據信號18.“客戶”數據表結構為&#xff1a;客戶編號、手機號、購物金額&#xff0c;合理的字段類型為( )A.字符型&#xff0c;字符型&#xff0…

軟件測試HW02-------fault error failure

程序一 問題一&#xff1a;i應該>0&#xff1b; 問題二&#xff1a; x為空 問題三&#xff1a;test x[2, 3, 5]; y 3;問題四:test: x[2]; y 3&#xff1b;程序二問題一&#xff1a;循環應該反過來;問題二&#xff1a;無;問題三&#xff1a;test:x[1];問題四:test: x[1,2,3…

Mathematica圖片局部變色

這篇博客來源于Stack-Exchange上的一個帖子&#xff0c;問題描述如下&#xff1a;如何將圖中的紅球變為藍球&#xff1f; 這個問題下面有很多答案&#xff0c;我選了最好的一個答案&#xff0c;代碼如下 img Import["C:/Users/1/Desktop/red.jpg"]; getReds[x_Image…

在WebLogic 12c上運行RichFaces

我最初以為我可以在幾個月前寫這篇文章。 但是我最終被不一樣的事情所淹沒。 其中之一是&#xff0c;它無法像我在4.0版本中那樣簡單地啟動RichFaces展示柜。 有了所有的JMS magic和不同的提供者檢查&#xff0c;這已經成為簡單構建和部署它的挑戰。 無論如何&#xff0c;我愿意…

Spring Boot系列教程一:Eclipse安裝spring-tool-suite插件

一.前言 一直使用eclipse&#xff0c;個人習慣選用Eclipsespring-tool-suite進行開發&#xff0c;特別注意Eclipse要選用對應的spring-tool-suite進行安裝&#xff0c;這點筆者浪費了好長時間&#xff0c;以下為對應的版本。eclipse-kepler.4.3.1–>springsource-tool-suite…

湖南工程學院計算機網絡考試,湖南工程學院 計算機網絡期末試卷試題

湖南工程學院 計算機網絡期末試卷試題湖南工程學院 計算機網絡 期末試題(計算機10級&#xff0c;90%的題目)1 從邏輯功能上看,計算機網絡可分為哪兩個子網?答&#xff1a;通信子網和資源子網 2 數據鏈路層的最基本功能答&#xff1a;數據鏈路層的最基本的功能是向該層用戶提供…

C#設計模式(11)——外觀模式(Facade Pattern)

一、引言 在軟件開發過程中&#xff0c;客戶端程序經常會與復雜系統的內部子系統進行耦合&#xff0c;從而導致客戶端程序隨著子系統的變化而變化&#xff0c;然而為了將復雜系統的內部子系統與客戶端之間的依賴解耦&#xff0c;從而就有了外觀模式&#xff0c;也稱作 ”門面“…

OS X Mountain Lion上的多個Java版本

在Mountain Lion之前&#xff0c;Java被捆綁在OS X中。似乎在升級期間&#xff0c;我在計算機上安裝的Java 6版本被刪除了。 顯然&#xff0c;在升級過程中卸載Java的原因是Java運行時存在的安全問題。通過這種方式&#xff0c;您不得不安裝可解決此安全問題的最新版本。 所以我…

Oracle鎖機制的總結【轉】

最近在研究Oracle鎖機制的時候發現網上的資料魚龍混雜將&#xff0c;很多將問題復雜化&#xff0c;讓人感覺沒有條理性。經過查詢原始理論資料&#xff0c;總結如下&#xff1a; 在數據庫理論中&#xff0c;我們知道。我們在執行并發訪問數據庫表時&#xff0c;如果沒有任何一致…

2020暨陽學院園林計算機考研考場,【圖片】2020考研,老學長教你如何規劃!【計算機考研吧】_百度貼吧...

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓二、關鍵一步——院校選擇我把各位同學的院校選擇階段分為以上幾個階段&#xff0c;因為考研這一年中&#xff0c;很多人的目標院校并不是固定不變的&#xff0c;而是隨著不同階段而改變的。學長我在大三下學期這一時間段內也多次更…

List Box 控件

1 //定義變量&#xff0c;并關聯控件與變量。IDC_RecvData為控件ID&#xff0c;recvData為控件對應的變量名 2 CListBox recvData; 3 4 DDX_Control(pDX, IDC_RecvData, recvData); 5 6 //向List Box控件IDC_RecvData中添加一行數據 7 CString str&#xff1b; 8 recvData.Ad…

JavaOne 2012:向上,向上和向外:使用Akka擴展軟件

在最后的社區主題演講后&#xff0c;我前往希爾頓金門大橋3/4/5觀看了維克多巴生 &#xff08; Viktor Klang &#xff09;的&#xff08; Typesafe &#xff09;“上&#xff0c;下&#xff0c;外&#xff1a;Akka”演講。 巴生&#xff08;Klang&#xff09;是Akka的技術主管…

華北科技學院計算機期末考試,華北科技學院 專業計算機 考試專用

1不能應用修剪命令“trim”進行修剪的對象是(D、文字) 。2. 命令行(B.不能隨意移動)3. 布爾運算中差集的熱鍵為(A.SU)4. 定距等分點用( C.DIST)命令5. 標高是以( B.厘米) 為單位6. 在建筑平面圖中用以指明朝向的是( B.指北針)7. A3圖紙的尺寸是( c.420x297)8. 既可以繪制直線&a…