为什么我的Spring ContextRefreshed事件被调用两次?

问题描述:

我有一个Spring ApplicationListener bean注册来侦听ContextRefreshed事件。但由于某种奇怪的原因,我在上下文初始化完成后得到了两个调用onApplicationEvent(ContextRefreshedEvent)方法。这是正常行为还是表示配置有问题?我为我的Servlet容器使用Jetty 8。为什么我的Spring ContextRefreshed事件被调用两次?

我相关的web.xml配置如下

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/config/spring/spring-config.xml</param-value> 
</context-param> 
<servlet> 
    <servlet-name>Spring</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value></param-value> 
    </init-param> 
<load-on-startup>1</load-on-startup> 
</servlet> 
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 
<servlet-mapping> 
    <servlet-name>Spring</servlet-name> 
    <url-pattern>/service/*</url-pattern> 
</servlet-mapping> 

谢谢!

即使您没有为您的DispatcherServlet指定contextConfigLocation,它仍会创建一个子上下文,而第二个刷新事件是针对该上下文的。使用event.getApplicationContext()来找出事件的上下文。

+1

就是这样!现在我可以使用ApplicationContext的'id'或'displayName'属性来区分这两个事件。 – Andre 2011-05-29 13:06:00

+3

或者,如果您@Autowire appContext(或实现ApplicationContextAware),您可以比较该appContext与事件中的那个。 – sourcedelica 2011-05-29 23:32:23

+0

@Andre一个noob的问题:如何从ContextRefreshedEvent访问ID或displayName? – 2015-11-27 14:39:36

它看起来像bug。

https://jira.springsource.org/browse/SPR-6589

如果您使用的3.0试试最新的可用版本是3.05。

+0

好吧,我们使用3.0.4所以我基本最低web.xml中的Spring应用程序我会给3.0.5一个镜头并报告我的发现。 – Andre 2011-05-29 00:18:59

+0

Bah,升级到3.0.5,这仍然是一个问题。 – Andre 2011-05-29 00:58:08

+0

甚至3.1也有同样的问题。 – Deckard 2013-05-31 09:12:38

我也有这个问题,但修复它。我正在将dataSource注入到DAO中(并用它实例化一个JdbcTemplate)......但我也为JDBCTemplate配置了一个Spring bean。

我应该注入我的DAO与jdbcTemplate ...,避免重复。

它发生在我身上,在不同的事件监听器上。 (ApplicationListener<AuthenticationFailureBadCredentialsEvent>

我怀疑ContextLoaderListener,当我从web.xml中删除声明时,该应用程序正常工作。然后,我不得不弄清楚什么是它的目的,的ContextLoaderListener的...

Role/Purpose of ContextLoaderListener in Spring?

有趣的答案有:

的ContextLoaderListener是可选的。只是提出一个观点在这里:你可以 开机而没有配置 的ContextLoaderListener ......只是 的DispatcherServlet