2012-11-12 34 views
1

我有一个基于Spring的WebApp。在我的应用程序方面,我有这个bean定义:什么会导致Spring IoC为每个WebApp实例化单个bean的多个实例?

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

我已经具有@Controller注释的一个春天调度servlet定义和一类,而我自动有线这个bean,期待春天到永远只实例化这个上课一次。但是,根据以下调试代码,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"); 
    } 
} 

可能是什么原因?

注:我用的弹簧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

有几个可能的原因:

  • 你的类是由这会使构造函数运行两次(相对于@PostConstruct回调总是每豆运行一次)一些CGLIB代理包裹 - 为你的类一次和一次继承代理

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

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

+0

你能解释一下你的第一点吗?为什么代理不能像其他任何继承类一样工作,并只调用一次super()(被代理的bean的构造函数)? –

1

一个单身人士是每个情境一次,而不是一次每热死一个宇宙。

打开日志记录,看看为什么/如果整个应用程序上下文被创建多次。