Reputation: 26882
I have a Spring based WebApp. In my application context, I have this bean defined:
<bean id="someSingleton" class="com.fake.SomeSingleton" scope="singleton"/>
I have the one Spring dispatch servlet definition and one class that has the @Controller
annotation to which I auto-wired this bean, expecting Spring to only ever instantiating this class once. However, according to the following debug code, Spring is instantiating this class more than once:
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");
}
}
What can be the cause?
Note: I use spring 3.1.2.RELEASE
EDIT:
Thanks to the hints I was given, I found the culprit.
Apart from the DispatcherServlet, I also had a ContextLoaderListener in my web.xml. After removing it, SomeSingleton only got instantiated once.
<!-- 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>
Upvotes: 1
Views: 472
Reputation: 340733
There are few possible reasons:
Your class is wrapped by some CGLIB proxy which causes the constructor to run twice (as opposed to @PostConstruct
callback which always runs once per bean) - once for your class and once for inheriting proxy
more likely, your bean is being picked up by two contexts: main one and Spring MVC one. This is a poor practice and you should avoid it. Check out if your SomeSingleton
class is not picked up by MVC dispatcher servlet context via some CLASSPATH scanning.
BTW in such a code it's safe to use simple AtomicInteger
instead of Semaphore
.
Upvotes: 2
Reputation: 100013
A singleton is once per context, not once-per-heat-death-of-the-universe.
Turn on logging and see why/if the entire app context is being created more than once.
Upvotes: 1