2014-02-18 45 views
3

我是Spring事件監聽器的一個問題在我的Web應用程序中,任何即時幫助將不勝感激。春季事件監聽器被調用兩次

事件監聽器被註冊並調用兩次,如果我有循環依賴。

我有服務類,這對其他方法

@Service(PBSTaskService.BEAN_NAME) 
public class PBSTaskServiceImpl extends StandardServiceImpl<ITask> implements   PBSTaskService,ApplicationListener<SurveyDefinitionPublishedEvent> 
{ 
    @Autowired 
    private AutoSelectTaskSliceRouteSyncService autoSelectTaskSliceRouteSyncService; // CYCLIC Dependency 
    @Override 
    public void onApplicationEvent(SurveyDefinitionPublishedEvent event) 
    { 
     System.out.println("PBSTSImpl"); // THIS IS CALLED TWICE 
    } 
... Other method with @Transaction Annotation 
} 


@Service(AutoSelectTaskSliceRouteSyncService.BEAN_NAME) 
public class AutoSelectTaskSliceRouteSyncServiceImpl implements AutoSelectTaskSliceRouteSyncService 
{ 
     @Autowired private PBSTaskService pbsTaskService; // CYCLIC dependency 
} 

現在,如果我從頭等艙刪除AutoSelectTaskSliceRouteSyncService依賴,OnApplicationEvent被調用一次,@Transaction註釋其他兩次。

我調試並發現, SimpleApplicationEventMulticaster.getApplicationListeners(myEvent):有兩個代理對象,一個包含Cglib和另一個默認的代理對象。但它只有兩個,如果它有循環依賴。如果我刪除循環依賴關係,它只有一個代理對象,並且那個代理對象被CGLIB提升。 我的Tx註釋: 我曾嘗試過使用proxy-target-class =「true或false」,但沒有運氣。

您可能希望有

https://jira.springsource.org/browse/SPR-7940?focusedCommentId=98988&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-98988

回答

2

了ApplicationEvent聽衆一起來看看在我們的web應用程序的很多地方被稱爲兩次。這是我們遇到的情景之一。

原因: 聽衆註冊兩次。兩個代理返回包裝在偵聽器的一個實例上。代理返回的是1.動態Jdk接口代理2. Cglib代理,當我們有@transactions註釋時。

要重新創建這三個點都必須:

  1. 聽衆必須實現ApplicationListener 2.你的聽衆必須有另一個類3.您的聽衆循環依賴必須與@Transaction註釋的一種方法。

我創建了一個單獨的項目,我可以用spring和hibernate重現它。如果2和3不在一起,那麼我們是安全的。

解決方案 我嘗試了很多與春季和交易配置調整,但沒有運氣。然後,當我將事務代碼移動到另一個類時,最終使用演示項目,以便聽衆沒有任何@transaction註釋,然後它爲我工作。

+0

在將服務類標記爲ApplicationListener時,在Grails 2.4.5中遇到同樣的問題。 – AndreyT

-1

在Spring中,用@Service或@Component所實現的實現ApplicationListener接口的類將接收重複事件。要解決此問題,只需接收單個事件,只需刪除@Service或@Compontent註釋。