美文网首页Spring
spring的bean被加载了两次

spring的bean被加载了两次

作者: coder_farmer | 来源:发表于2017-12-08 10:19 被阅读670次

    一、情况

    今天在调试spring框架的web项目时,启动的时候发现某个@Service注解的bean被加载了两次。

    因为我看见@PostConstruct的方法被执行了两次。

    二、spring的配置如下

        <context-param>  
                <param-name>contextConfigLocation</param-name>  
                <param-value>  
                    classpath:spring-servlet.xml  
                </param-value>  
            </context-param>  
          
        <listener>  
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
            </listener>  
          
        <servlet>  
                <servlet-name>springServlet</servlet-name>  
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
                <init-param>  
                    <param-name>contextConfigLocation</param-name>  
                    <param-value>classpath:spring-servlet.xml</param-value>  
                </init-param>  
                <load-on-startup>1</load-on-startup>  
            </servlet>  
    

    1、问题就出在ContextLoaderListener和DispatcherServlet,他们都可以引入spring,而且每个引入都会实例化一次bean。如果把两个引入方式配置到同一个文件,那么就会导致一个bean被实例化两次。但是,当我们使用Spring Bean的时候,只会用到DispatcherServlet下的Bean,而不会用到ContextLoaderListener下的Bean,这就会导致ContextLoaderListener的bean不会被用到,具体为什么,且看下面的第三点。

    2、所以我就把ContextLoaderListener注释掉,而且,亲测所有配置的bean都会被加载,而且只会被加载一次。

    三、使用ContextLoaderlistener和DispatcherServlet引入Spring的区别

    1、ContextLoaderListener和DispatcherServlet都会生成一个WebApplicationContext(上下文),分别以不同的name存放在容器中。
    2、同一个容器里,只允许有一个ContextLoaderListener但是可以用多个DispatcherServlet。 DispatcherServlet的context总是ContextLoaderListener的context的子类。
    3、在获取bean的时候,会先从DispatcherServlet的context获取,如果没有再从ContextLoaderListener的context获取,这就解释了上面的第一点。
    4、如果两者用的是同一份配置文件,或者他们的定义bean有交叉就会造成部分bean永远不会被用到(泄漏)。
    5、DispatcherServlet还会加载与SpringMVC相关的bean,如RequestMapping。。。。

    相关文章

      网友评论

      本文标题:spring的bean被加载了两次

      本文链接:https://www.haomeiwen.com/subject/ejjlixtx.html