2017/5/19 9:34:22 使用markdown重新编辑,并引入新的参考链接。
2017/10/26 19:58:49 修改格式.第一个版本发布于 2017-02-08 23:23
通过实现ApplicationListener来达到在spring容器加载完毕时来作出某些自定义的操作,关于这一点想必很多人都知道了,本篇文档当然不会是这类被很多前人讲述了一遍又一遍的东西。
今天所要讲的是在SpringMVC中在上面实现的方法会被Spring回调两次,如果你是因为这个问题而找到了这篇文章,那么恭喜你达到了终点,在下面的内容里我会给出解决方案和产生这种现象的原因。
1. 解决方案
不要在spring.xml
中注册上面那个实现了ApplicationListener<ContextRefreshedEvent>
接口的类,去spring-mvc.xml
中进行注册即可。
2. 原因
我们一般会有spring.xml
和spring-mvc.xml
两个文件, 针对这两个文件.
- Spring里获取bean的逻辑是:如果在自身的容器中没有找到该对象,那么就去parent container中查找(相关源码参见
AbstractBeanFactory
类中的doGetBean
方法–[(parentBeanFactory != null && !containsBeanDefinition(beanName))
]) - 而Spring中的事件通知逻辑如下: 先向自身的容器发起事件通知,如果本容器有parent container存在,则在parent container进行一次通知(相关源码参见
AbstractApplicationContext
类中的publishEvent
方法) - 所以:
- parent container(
spring.xml
作为配置文件)
由ContextLoaderListener
(org.springframework.web.context.ContextLoaderListener
)载入 - child container(
spring-mvc.xml
作为配置文件) – 由DispatcherServlet
(org.springframework.web.servlet.DispatcherServlet
)载入
- parent container(