One of the common misunderstanding among Spring Framework developers is the difference between Spring Singleton and Java Singleton. Interestingly this turns out to be one of the popular interview questions for spring developers to check the understanding of singleton concepts.
If you are working on Java and Spring technologies, it is quite important to know the clear difference between Java Singleton and Spring Singleton. In this post I will explain the basic difference between both the singleton concepts. If you are not already familiar about the Singleton pattern, please read our tutorial about Java Singleton Pattern.
Java singleton class is per classloader and Spring’s singleton is per application context.
Java Singleton
Note that there is nothing like pre-defined rules for implementing the singleton classes, but the class should be instantiated only once per classloader. Here is the basic steps for implementing the Java Singleton class.
- When you say singleton class, there should be only one instance of that class can be created.
- Constructor of that class has to be made as private to avoid instantiation from external classes.
- Declare a static variable to store the instance for that class.
- Declare a method that returns the instance of that class.
With the above basic rules, one can classify Java Singleton implementation into the following categories:
- Eager Initialization
- Static Block Initialization
- Lazy Initialization
- Thread Safe Singleton
Eager Initialization
In eager initialization, the singleton instance is created at the time of loading class loading. This is the easiest way to create the singleton instance for your singleton class. But, the main drawback of this approach is that the instance will be created even though it is not used by any of the client application. In this approach, you have to just create instance in the static variable declaration. This approach doesn’t provide any option for exception handling.
Here is the example for eager initialization of singleton instance:
public class EagerInitialization { private static final EagerInitialization instance = new EagerInitialization(); private EagerInitialization(){} public static EagerInitialization getInstance(){ return instance; } }
Static Block Initialization
This also falls under the eager initialization, the only difference is that instance creation is completed inside the static initializer block. This approach doesn’t provide any option for exception handling.
Here is the example for static block initialization of singleton instance:
public class StaticBlockInitialization { private static StaticBlockInitialization singletonInstance; private StaticBlockInitialization(){} static{ try{ singletonInstance = new StaticBlockInitialization(); }catch(Exception e){ throw new RuntimeException("Exception occured while creating the singleton instance"); } } public static StaticBlockInitialization getInstance(){ return singletonInstance; } }
Lazy Initialization
In this approach, we are creating the instance only after loading the class and first invocation of the instance. This will avoid pre-initializing the instance where you don’t need the instance it is requested by the service.
This approach works fine when this class is executed in the single threaded environment, but this will not work fine in the multi-threaded environment when multiple threads are trying to get the new instance simultaneously (Read : Threading in Java).
Here is the simple example for Java Singleton class using lazy initialization approach:
public class Main { public static void main(String args[]) { Singleton singleton = Singleton.getInstance(); System.out.println("Value 1 : " + singleton.getValue()); singleton.setValue(20); Singleton singleton2 = Singleton.getInstance(); System.out.println("Value 2: " + singleton2.getValue()); } } class Singleton { private Singleton() {} private static Singleton singleton; private int value = 10; public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
Thread Safe Singleton
This is similar to the above approach except that the method used for creating the singleton instance is synchronized. This approach is the most safest and best solution to implement the singleton instance, but it has the performance issues when multiple threads to trying to access the instance simultaneously.
Here is the example for thread safe singleton instance:
public class ThreadSafeInstance { private static ThreadSafeInstance singletonInstance; private ThreadSafeInstance(){} public static synchronized ThreadSafeInstance getInstance(){ if(singletonInstance == null){ singletonInstance = new ThreadSafeInstance(); } return singletonInstance; } }
Spring Singleton
The scope of the Spring singleton is best described as per container and per bean. If you define a bean for a particular class in a single container, spring container will create only one instance for the class. In spring, singleton is termed as one of the scope for defining the beans. Singleton scope is the default scope for spring beans.
Here is the example declaration of Spring’s singleton beans:
<bean id="bookService" class="com.foo.DefaultBookService"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <bean id="bookService" class="com.foo.DefaultBookService" scope="singleton"/>
How Spring Singleton Works?
When you think of singleton instance, the first question pop-up in your mind is the thread safety of your application. Spring’s singleton beans are shared among all the requests when your application is running on the multi-threaded environment. How to ensure that your program is thread-safe?.
It is important to remember that your singleton beans should not store any state information. Because the bean instance created once will be shared across all the threads that are requesting for that spring bean. If you inject an object to spring’s singleton bean, it is wired only once and it never get refreshed. It is ideal to make all the controllers as the singleton beans and value objects as the prototype beans.
If you want your prototype beans to be injected every time, then you have to implement the method injection. Otherwise, there is no way to make your singleton object to re-initiate the prototype beans every time. Please read my tutorial about method injection to understand how to instantiate value objects every time it is requested and inject into the singleton objects.
Look this code snippet:
@Controller public class SampleController { int i = 0; @Autowired private ValueObject vo; }
In the above code snippet, ValueObject is declared as prototype bean in the XML configurations. However, this object will be injected only once when first time SampleController instance is created. After that the same object will be used for all the requests. In that case, the variable i and vo, should not maintain any state information, otherwise those will be across all the threads.
For example, when the variable i is incremented by one request is shared to another thread. This will lead to confusion and the application won’t be thread safe. To avoid that, don’t declare any instance variable that stores the state information in singleton beans.
Summary
I hope this post would have provided the basic concepts behind Java singleton and Spring singleton. Java singleton is per classloader and spring singleton is per application context for a bean. Also learns about the different scopes in the spring beans to understand when you have to use the singleton bean in spring.