I have a graph of Spring beans which autowire each other. Heavily simplified illustration:
<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>
...
public class Foo {
@Autowired Bar bar;
@Autowired Baz baz;
}
public class Bar {
@Autowired Foo foo;
}
public class Baz {
@Autowired Foo foo;
}
All of these beans don't have scope specified which imply they are singletons (making them explicit singletons doesn't change anything, I've tried).
The problem is that after the instantiation of a single application context, instances of Bar
and Baz
contain different instances of Foo
. How could this happen?
I have tried to create public no args constructor for Foo
and debugging has confirmed Foo
is created more than once. The stack trace for all of these creations is here.
I have also tried to enable debug logging for Spring, and among all other lines, got the following:
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
I understand that my beans are cross-referencing each other, but I would expect Spring framework to respect singleton scope and initialize a singleton bean once, and then autowire it to whoever wants it.
The interesting fact that if I use old school private
constructor with public static Foo getInstance
accessor, this works just fine - no exceptions are thrown during the context setup.
FWIW, I am using Spring version 3.0.5 (also tried with 3.1.2, same results) with o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
constructor.
I can easily convert my code to use static initializer but I want to understand why would Spring behave this way. Is this a bug?
EDIT: Some additional investigation showed that
context.getBean(Foo.class)
always return the same instance of Foo
.@Autowired
with setters (about 20 usages of this bean) still results multiple constructions of this object, but all dependencies are injected with the same reference.To me above suggests that this is a Spring bug pertaining to @Autowired
implementation. I am going to post to Spring community forums and post back here if I manage to obtain anything useful.
Well-designed singleton can have only one instance per application. Creating of multiple instances is a mistake in the application design.
In software engineering, the multiton pattern is a design pattern which generalizes the singleton pattern. Whereas the singleton allows only one instance of a class to be created, the multiton pattern allows for the controlled creation of multiple instances, which it manages through the use of a map.
When the Spring container creates a bean with the singleton scope, the bean is stored in the heap. This way, all the concurrent threads are able to point to the same bean instance.
The Singleton is a useful Design Pattern for allowing only one instance of your class, but common mistakes can inadvertently allow more than one instance to be created.
Child context(s) can reinstantiate the same singleton beans if you are not careful with context:component-scan annotations (there are other Spring context scan annotations as well such as MVC ones and others). This is a common problem when using Spring servlets in web applications, see Why DispatcherServlet creates another application context?
Make sure you are not re-scanning your components in child contexts, or you are scanning only specific packages/annotations and excluding said packages/annotations from root context component scan.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With