春天的事件监听器被两次调用

Pra*_*v T 5 spring event-listener

我是Spring事件监听器的问题在我的Web应用程序中,任何即时帮助将不胜感激。

如果我具有循环依赖性,则将事件监听器注册并调用两次。

我有服务类,这在其他方法上有@transaction注解

@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
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我从第一类中删除了AutoSelectTaskSliceRouteSyncSyncService依赖项,则将一次调用OnApplicationEvent,否则将调用两次。

我调试并发现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

rou*_*gou 6

从 Spring 4.2 开始,您可以放弃实现 ApplicationListener 并在任何托管 bean 中的方法上使用新的 @EventListener 注释。这应该可以帮助您避免任何冲突。

以下是https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2的示例

@Component
public class MyListener {

    @EventListener
    public void handleContextRefresh(ContextRefreshedEvent event) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*v T 3

ApplicationEvent 侦听器在我们的 Web 应用程序中的更多位置被调用两次。这是我们遇到的场景之一。

原因:听众注册了两次。返回的两个代理包裹在一个侦听器实例上。当我们有 @transactions 注解时,返回的代理是 1. 动态 Jdk 接口代理 2. Cglib 代理。

要重新创建这三点必须:

  1. 您的侦听器必须实现 ApplicationListener 2. 您的侦听器必须与另一个类具有循环依赖关系 3. 您的侦听器必须有一个用 @Transaction 注释的方法。

我创建了一个单独的项目,我可以在其中使用 spring 和 hibernate 重现它。如果 2 和 3 不在一起,那么我们就是安全的。

解决方案我尝试了对 spring 和事务配置的许多调整,但没有成功。最后,在我的演示项目中,我将事务代码移至另一个类,以便侦听器没有任何 @transaction 注释,然后它对我有用。