是什么导致Spring IoC为每个WebApp实例化一个单独的bean实例?

时间:2012-11-12 18:45:40

标签: spring dependency-injection

我有一个基于Spring的WebApp。在我的应用程序上下文中,我定义了这个bean:

<bean id="someSingleton" class="com.fake.SomeSingleton" scope="singleton"/>

我有一个Spring调度servlet定义和一个具有@Controller注释的类,我自动连接了这个bean,期望Spring只能实例化一次这个类。但是,根据以下调试代码,Spring会多次实例化此类:

private static final Semaphore SANITY_CHECK = new Semaphore(1);

public FakeSingleton(){
    if(!SANITY_CHECK.tryAcquire()){
      log.error("why?");
      System.exit(-1);
    else{
      log.error("OK");
    }
}

可能是什么原因?

注意:我使用spring 3.1.2.RELEASE

修改 感谢我给出的暗示,我找到了罪魁祸首 除了DispatcherServlet之外,我的web.xml中还有一个ContextLoaderListener。删除后,SomeSingleton只实例化一次。

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>FakeService</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

2 个答案:

答案 0 :(得分:2)

可能的原因很少:

  • 你的类被一些CGLIB代理包装,导致构造函数运行两次(而不是@PostConstruct回调,每个bean总是运行一次) - 一次为你的类,一次为继承代理

  • 更有可能的是,你的bean被两个上下文拾取:main和Spring MVC。这是一种不好的做法,你应该避免它。通过一些CLASSPATH扫描检查MVC调度程序servlet上下文是否没有获取SomeSingleton类。

在这样的代码中BTW使用简单的AtomicInteger代替Semaphore是安全的。

答案 1 :(得分:1)

单身人士在每个环境中都是一次,而不是每次热量死亡一次。

打开日志记录,查看原因/是否多次创建整个应用上下文。