Spring ApplicationListener在webapp上被解雇两次

Spring ApplicationListener在webapp上被解雇两次,spring,spring-mvc,Spring,Spring Mvc,我有一个应用程序侦听器,每个webapp启动只执行一次,因为它加载基本的用户信息数据 public class DefaultUsersDataLoader implements ApplicationListener<ContextRefreshedEvent> { @Override @Transactional public void onApplicationEvent(ContextRefreshedEvent e) {...} } public类Defaul

我有一个应用程序侦听器,每个webapp启动只执行一次,因为它加载基本的用户信息数据

public class DefaultUsersDataLoader implements ApplicationListener<ContextRefreshedEvent> {
  @Override
  @Transactional
  public void onApplicationEvent(ContextRefreshedEvent e) {...}
}
public类DefaultUsersDataLoader实现ApplicationListener{
@凌驾
@交易的
ApplicationEvent(ContextRefreshedEvent e){…}上的公共无效
}

不知何故,它会执行两次:应用程序启动时和第一个请求到达服务器时。为什么会发生这种情况以及如何防止这种情况?

通常在Spring MVC应用程序中,您既有
ContextLoaderListener
又有
DispatcherServlet
。这两个组件都创建自己的
ApplicationContext
,这两个组件依次触发
ContextRefreshedEvent

DispatcherServlet
使用由
ContextLoaderListener
创建的
ApplicationContext
作为其父级。从子上下文激发的事件将传播到父上下文


现在,如果您在根上下文中定义了一个
ApplicationListener
(由
ContextLoaderListener
)它将接收两次事件。

不要用@EventListener注释侦听器类的方法,谢谢。我用
e.getApplicationContext().getParent()排除了这一点null,但它似乎有点不正常。我想知道是否有更好的实践方法?不是真的,如果已经调用了侦听器,则可以切换布尔值。如果只是加载一些数据,而您使用的是Spring 4.1,那么您也可以使用。您可能还希望确保web上下文不会实例化除控制器之外的任何bean。i、 e.强制组件扫描基本包只包括一个“web”包,它是控制器和其他此类bean的父级。这应该确保您的侦听器只存在于根上下文中,因此只会拾取根上下文事件。感谢您,查看event.applicationcontext(id、父级和祖级)(在我们的closeEvent示例中)可以更好地了解每个调用方的上下文配置和层次结构(除了根应用程序上下文之外还有servlet ctx)。我也有同样的问题。删除@EventListener解决了这个问题。有人能解释一下吗?