Spring @EventListener 異步中使用condition的問題及處理
@EventListener 異步中使用condition的問題
@EventListener是spring在4.2+推出的更好的使用spring事件架構的方式,並且異步方式也很好設定
但是在spring4.2.7版本上使用eventlistener的condition 的使用需要註意以下情況可能失效:
condition 使用例子如
@EventListener(condition = "#event.isAsync")
1. 需要對同一個事件進行區分同步異步
2. 使用condition來進行過濾
例如:
需要對事件用condition進行區分同步異步
@Async @EventListener(condition = "#event.isAsync") public void handleOrderCreatedEventAsync(TestEvent event) { } @EventListener(condition = "#event.isAsync == false") public void handleOrderCreatedEvent(TestEvent event) { }
修正的做法,是使用兩個事件區分即
@Async @EventListener public void handleOrderCreatedEventAsync(TestEventAsync event) { } @EventListener public void handleOrderCreatedEvent(TestEvent event) { }
還不清楚,在更高的版本上是否已經有進一步的修正,待以後研究
Spring事件的condition使用說明
在開發中使用瞭spring的事件機制,但是發現瞭一個問題:如果多個發佈的事件對象是同一個類型,而除瞭使用瞭這個事件類型作為參數的事件處理方法還是多個,那就無法區分到底要執行哪個處理方法瞭,除非你想每個處理方法都執行。
如下是我的事件處理代碼聲明
@Async @EventListener public void handleExport(ExportExcelMessage<DTO> exportMsg){ }
這裡的業務場景是異步導出Excel。直接用@EventListener來聲明事件處理方法。
在controller中我如此調用
publisher.publish(new ExportExcelMessage<>(reqDTO));
ExportExcelMessage是個事件對象,包含事件基本屬性,reqDTO就是查詢條件數據瞭。
開始感覺沒有問題。後來突然有一個相同類型入參(reqDTO)的導出功能。
這樣處理方法就有問題瞭。出現處理方法的重復執行。
隨便上網一查,簡單,EventListener直接加condition屬性就搞定。網上是這樣的;
@EventListener(condition="#exportMsg.source=='xxx'")
其中這個source就是ExportExcelMessage類的的一個屬性,用來區分到底是誰發起的事件。
使用SPel表達式,直接引用的方法的參數名,單我試驗是不行的,異常顯示exportMsg應該是個null。
估計應該能在方法參數上加註解來處理吧,就像Contrller的@WebParam一樣,但我一時也沒找到。
最後,直接看人傢的代碼註釋,。。。。自己笨的可以瞭。
如下就解決瞭
@EventListener(condition = "#root.args[0].source == 'xxx'")
root.args就是參數的數組,直接用下標取就好瞭。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Spring的事件機制知識點詳解及實例分析
- 詳解Spring事件發佈與監聽機制
- SpringBoot事件發佈和監聽詳解
- springboot如何開啟一個監聽線程執行任務
- java和Spring中觀察者模式的應用詳解