OK, I know this sounds like another one of those “a white horse is not a horse” arguments, but from my observation on the Spring forums and other blog reading, some clear distinction between the semantics of a Spring singleton and a classical Java singleton has become much necessary. The overloaded term has caused quite some confusion, especially for someone who has just started picking up Spring.
First let’s examine how a bean is made a singleton in Spring:
- <bean id="foo" class="Foo" singleton="true">
What the ‘singleton’ attribute really makes Spring do is to cache and always return the same bean instance for all the requests on this bean. As far as the comparison to a classical Java singleton is concerned, there are two distinctions that need to be noted here:
1. The caching of a bean instance happens only within a single Spring
ApplicationContext instance – referred to as the “Spring IoC container” in Spring documentation. So obviously if I have another bean defined with the same id and the same class in a separate
ApplicationContext instance, that one would be a completely different one. (Note that here we are talking about
ApplicationContext instances, not context definition XML files, because more than one file can be loaded into one context instance. As far as the singleton scope is concerned, it is the instance not the files that counts.) In contrast, if we look at a Java singleton, its scope of singularity applies to the “universe” managed by the classloader that loaded this class.
2. When a bean reference is requested from an application context, the id or the name is used to identify the bean wanted. On the other hand, when we call
Bar.getInstance(), we are really using the class
Bar to identify what we instend to receive. If that didn’t sound like something significant, consider a scenario where two beans of the same class are defined in the same
- <bean id="foo1" class="Foo" singleton="true">
- <bean id="foo2" class="Foo" singleton="true">
There will be two bean instances created in this context, both of type
Foo, but one under id ‘foo1′, another under id ‘foo2′. Clearly that’s behavior we’d never see in Java singletons.
Having noted the two distinctions above, it becomes clear that a Spring singleton has some semantics rather orthogonal to those of a Java singleton – “orthogonal” in the sense that neither is the singularity of a Spring singleton meaningful in any scope definition based on classloaders, nor is a Spring singleton instance associated to any specific class. On the other hand, as we all would recognize, those are the two fundamental characteristics of a Java singleton.
Hopefully, this confusion will be clarified to some extent in Spring 2.0, with the newly introduced ‘scope’ attribute and the session, request, and global session scopes. Also Section 3.4 Bean Scope in the Spring 2.0 Reference explicitly puts out a warning note on the difference between the Spring singleton scope and the classical Singleton Pattern. Although I still think that it could have had the issue completely addressed, had the scope value “singleton” been renamed to something like “container” altogether – but then, I can also see some new confusion arising from that, like “how is this supposed to map to the singleton thing from before?”