[转]spring项目中component被重复加载两次的原因及解决方案

引用

DispatcherServlet 和 ContextLoaderListener 的关系,到底用哪个?

该文章用于存档,具体请查看原文章。

而且图片都是引用的。

引用文章

我们先看下这两个东东的配置方法:

这里写图片描述

对于contextConfigLocation参数,有2个地方可以配置:
1)context-param 是全局性配置
2)servlet下的init-param 是局部性配置
若以上两处都设置了一个相同的bean配置文件路径,那么该文件内配置的bean会被初始化2次,所以一个配置文件只能选择一种配置位置;

项目中使用spring框架有2种方式:
1)listener下的ContextLoaderListener 是一种引入方式,默认读取/WEB-INF/applicationContext.xml
2)若是spring-web项目,DispatcherServlet 也是一种引入方式,默认读取/WEB-INF/${servlet-name}-servlet.xml

倘若以上2种配置都引入了,那么全局性的bean配置文件会被加载2次;而且2种方式的各自配置文件里的配置项在某种意义上并不是合并互补,而是各成一个体系(虽然普通的bean看似是都加载到全局上下文来了,但还是有一些特殊bean和配置项没有按预期的那样工作);

比如/WEB-INF/applicationContext.xml文件下里的AOP声明式配置:

<!--aop 行为-->
<bean id="himvn" class="com.tangbao.hellomvn.Himvn" />
<!--aop 注释方式-->
<bean id="hiaspect" class="com.tangbao.hellomvn.Hiaspect" />
<!--aop config-->
<aop:aspectj-autoproxy />
<aop:config>
    <aop:aspect id="aoplianxi" ref="himvn">
        <aop:pointcut id="test1" expression="execution(* com.tangbao.controller.RestlessController.RestlessController(..))"></aop:pointcut>
        <aop:before method="sayHi" pointcut-ref="test1"></aop:before>
        <aop:after method="sayHi" pointcut-ref="test1"></aop:after>
    </aop:aspect>
</aop:config>

若只是在全局配置项中,而没有在DispatcherServlet 中加载,那么此aop会无效。

这里写图片描述

所以,在web项目中,就不要使用ContextLoaderListener 和全局配置contextConfigLocation参数了,统一在DispatcherServlet 下配置,应该就不那么混乱了。如下:

这里写图片描述

这样结果就如我们的预期:多bean配置文件不会出现重复加载,所有aop配置也都生效。

以上论点是在spring4.3.1下亲测所得,当然是从表现猜测本质的,还没有真正去研读Spring的源码,所以若有原理说错之处,还望各位看官指出!

猜你喜欢

转载自blog.csdn.net/cdnight/article/details/82658355