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。

推薦閱讀: