Spring Singleton vs Singleton Pattern
Spring singletons are not Java Singleton. In this post, let’s go over the difference between Spring Singleton vs Singleton Pattern.
Introduction
Singleton scope is the default scope in Spring. Spring container create exactly one instance of the object defined by that bean definition.
Many times, we start comparing this design with the Singleton pattern as defined in the Gang of Four (Gof) book.
1. Singleton Scope vs Singleton Pattern
Singleton scope in Spring is not same as singleton pattern. Some of the main differences between these 2 are
- Singleton pattern ensures one instance of a particular class of per class loader.
- Spring Singleton is “per container per bean”.
If you pay close attention, these are entirely different design in terms of how they define singleton.
1.1 Singleton Scope Example
Singleton instance in Spring will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
Let’s work on an example to understand it more clearly.
public class CustomerAccount {
private String name;
public CustomerAccount() {
}
public CustomerAccount(String name) {
this.name = name;
}
@Override
public String toString() {
return "CustomerAccount{" +
"name='" + name + '\'' +
'}';
}
}
Spring Boot main method
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean(name = "bean1")
public CustomerAccount customerAccount(){
return new CustomerAccount("Test User 1");
}
@Bean(name = "bean2")
public CustomerAccount customerAccount1(){
return new CustomerAccount("Test User 2");
}
}
Let’s understand this code.
- We created 2 instances of the same class with different bean id.
How many instances created by Spring IoC container for above example?
- 2 separate instances in the container bind to their Id’s?
- 1 instance bind to 2 bean ids?
1.2 Test Case
To get an answer to the above questions, let’s create a unit test case for our example.
@RunWith(SpringRunner.class)
@SpringBootTest
public class SingletonScopeTest {
private static Logger log = LoggerFactory.getLogger(SingletonScopeTest.class);
@Resource(name = "bean1")
CustomerAccount account1;
@Resource(name = "bean1")
CustomerAccount duplicateAccount;
@Resource(name = "bean2")
CustomerAccount account2;
@Test
public void testSingletonScope(){
log.info(account1.getName());
log.info(account2.getName());
log.info("account are equal:: {}", account1 == account2);
log.info("Duplicate Account :: {}", account1 == duplicateAccount);
}
}
Output
2018-01-15 21:53:29.171 INFO 8421 --- [ main] com.example.demo.SingletonScopeTest : Test User 1
2018-01-15 21:53:29.171 INFO 8421 --- [ main] com.example.demo.SingletonScopeTest : Test User 2
2018-01-15 21:53:29.171 INFO 8421 --- [ main] com.example.demo.SingletonScopeTest : account are equal:: false
2018-01-15 21:53:29.172 INFO 8421 --- [ main] com.example.demo.SingletonScopeTest : Duplicate Account :: true
On checking the output, We found
- we can understand that Spring returns two different instances.
- More than one object of the same class for the singleton scope.
For a given Id, Spring container maintain only one shared an instance of singleton bean. In our example
- Spring Ioc container created 2 instances of the same class based on bean definition and binds them with ids.
- Spring bean definition work as a key-value pair, the key is mapped to bean id and value mapped to the bean instance.
- Each key reference returns the same bean instance (refer to “bean1” always return bean instance associated with id “bean1”).
Summary
Spring Singleton is very different from Singleton pattern. Spring guarantees to create only one bean instance for given bean id definition per container.Singleton pattern ensures that one and only one instance is created per ClassLoader.
It will be nice for you to elaborate how to implement a more like singleton pattern with SBoots. You are showing the problem but not the solution.
Hello JB,
The intend fo this post is to clear a common confusion between these two as most people mix these two entirely different concepts.I like your recommendation to implement both with SB.I will surely plan to write a post on this.