我有一个基于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>
答案 0 :(得分:2)
可能的原因很少:
你的类被一些CGLIB代理包装,导致构造函数运行两次(而不是@PostConstruct
回调,每个bean总是运行一次) - 一次为你的类,一次为继承代理
更有可能的是,你的bean被两个上下文拾取:main和Spring MVC。这是一种不好的做法,你应该避免它。通过一些CLASSPATH扫描检查MVC调度程序servlet上下文是否没有获取SomeSingleton
类。
AtomicInteger
代替Semaphore
是安全的。
答案 1 :(得分:1)
单身人士在每个环境中都是一次,而不是每次热量死亡一次。
打开日志记录,查看原因/是否多次创建整个应用上下文。