1

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

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

我有一个 Spring dispatch 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>
4

2 回答 2

2

有几个可能的原因:

  • 您的类由一些 CGLIB 代理包装,这会导致构造函数运行两次(与@PostConstruct每个 bean 始终运行一次的回调相反)- 一次用于您的类,一次用于继承代理

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

顺便说一句,在这样的代码中,使用 simpleAtomicInteger而不是Semaphore.

于 2012-11-12T18:47:51.540 回答
1

单例是每个上下文一次,而不是每个宇宙热死亡一次。

打开日志记录并查看为什么/是否多次创建整个应用程序上下文。

于 2012-11-12T18:47:35.743 回答