Singleton Design Pattern in Java and Spring With Example – Easy Explanation Guaranteed!

This tutorial is intended for people who want understand everything about singleton design pattern in Java and Spring with easy example. After you finish watching this tutorial, you will not only be confident with the concept, but you can use the same example in your next interview and impress the interviewer! 😎

Also, don’t forget to add this skill in your resume! Singleton is one of the most popular design patterns in the world, or even in universe or even in the galaxy! (Hope it’s not too bad of a joke 😕)

Note : In order to keep this tutorial ‘short’ and ‘to the point’. I prefer not to show full examples initially, but only some key aspects to explain you the concept. However, in the end we will go step by step on how everything is done along with source code. Just sit back and enjoy for now. Sounds good?

Goal(s) of this tutorial..

  • Familiarize you with  Singleton design pattern in Java and Spring with examples
  • Make you feel confident with interviews
  • Help you add this new skill in your resume

Why learn Singleton Design Pattern?

  • Crucial for interviews
  • Singleton design pattern has certain advantages (You will learn them in this tutorial)
  • Understanding of Singleton design pattern is necessary to understand Spring Framework

Before you proceed, make sure you have..

  1. Some knowledge on Java Programming
  2. Willingness to go though this tutorial completely without distractions
  3. Good to have : Some understanding on Spring Framework

Recommended course(s) : Java Programming , Spring Core Framework , Spring MVC with Spring Boot

[the_ad id=”2285″]

Topics that you will understand finally..

This tutorial on singleton design pattern in Java and Spring will cover the following topics,

  • What is singleton design pattern?
  • Why use singleton design pattern & it’s advantages?
  • When not to use single design pattern?
  • Singleton in Java with code example
  • Singleton on in Spring with code example
  • Eager vs Lazy loading in spring

Video version : If you are a fan of video tutorials like me, then you can watch the video version of this tutorial which is more elaborated. Or better yet, read the article and then watch this video!

Setup requirements

You just need to have JDK installed. If you are able to run Java programs, you are good to go!

For spring example though, It’s recommended that you have some idea on Maven dependencies. Hence, we will talk about it real quick in next section (Feel free to skip the next section, if you already know maven)

A little bit about maven

This section is dedicated to familiarize you with couple of features that maven has to offer.

JDK doesn’t come with all the libraries that you’d ever need right? Chances are that, your project depends on another project or external libraries. If you are talking about large scale enterprise applications, we are talking about some big numbers.

It’s hard and unreliable to manually search the dependencies over the internet, download them, store them in local machine and then import them in to your project.

Wouldn’t it be nice if you had a tool, where all you have to do is to add an XML tag in one special file (pom.xml) , and that tool will do all the heavy lifting? I mean, the tool will download and store the libraries in the classpath on your behalf. That is exactly what is Maven.

The xml tag that you add in pom.xml may look something like this

<dependency>
     <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
     <version>4.1.0</version>
</dependency>

By specifying the above tag, we are asking maven to download Apache-POI library of version ‘4.1.0’ in to our class path. Maven will not only download the dependent library, but also the libraries that the dependent library depends on! (Sounds like a tongue twist, but it’s true!)

I found that tag with a quick google search (Surely better than me manually downloading bunch of .jar file and storing them in the classpath!)

Well actually, maven is much more than that. But, this is the feature of it, which is very relevant for this tutorial.

Forget about what is ‘groupid’,’version’ etc. That will take us to maven world. Just remember, that if we need to use another library, we’d add an xml tag in pom.xml.

If you are still disparate to learn Maven, I recommend this Maven course.

 

What’s a Singleton Design Pattern

Singleton Design Pattern ensures that you will be able to create only one Instance of a class and you will use the same instance across your application.

I am sure your sub-cautious mind is wondering ‘Why?’,’What?’,’How?’. That’s what we will discuss in the rest of the tutorial.

Creating a singleton class

Take a look at the following code..

public class SingletonExample {

	private static SingletonExample instance;

	private SingletonExample() {
	}

	public static SingletonExample getInstance() {
		if (null == instance) {
				instance = new SingletonExample();
		}
		return instance;
	}

	public void businessLogic(String message) {
		System.out.println("Executing Business logic..." + message);
	}
}

And tell me if you can create more than one instance of it? No, you can’t! Let me explain..

From the above code, you see a Private constructor. Since the constructor is not public, you can’t construct/create objects from outside the class. But, only from within the class.

With this we blocked creation of new instances. But, that’s not what we wanted. We want to be able to create an instance (Even from outside of the class) and the same instance must be used every time. Well, that’s what ‘getInstance()’ method does.

At first we are checking to see if the ‘Instance’ is null (It would be null, the first time we call it). If it is ‘null’ we will go ahead and create the instance of the same class. For all the subsequent calls, the condition won’t be met and the same instance will be returned every time.

If you want to test this, just create another class and call this method multiple times. Each time you call, try to print the Hash code of the returned instance. You’d notice that the same hash code would be printed every time.

But, we have one serious flaw in the above code. Can you guess what it is?

Well, the above class will generate multiple instances if multiple threads request for the instance at the same time. There by destroying the very purpose of singleton pattern. I mean, lets say thread t1 entered first by meeting the condition “null == instance”. Now, there is a possibility that another thread (Say t2) can enter meeting the same condition “null == instance” as it may be the case that ‘instance’ is still not created and assigned!

I mean, think about it (Again, watch video for more elaborated explanation)

So the solution is to implement ‘lock’ mechanism by using ‘synchronized’ block (This is all core java! Out of the scope of this tutorial). Code below..

	public static SingletonExample getInstance() {
		if (null == instance) {
			synchronized(SingletonExample.class) {
				if (null == instance)
				instance = new SingletonExample();
			}
		}
		return instance;
	}

 

Why Singleton Design Pattern?

Take a minute and guess why..

If you notice, we don’t have any properties in the above example. That means, the instances that we create from that class will not have a ‘State’. When an object doesn’t hold a state, they are thread safe! No matter how many threads would need an instance of the above class, they are all one and the same.

Now, here’s the thing! When you are creating the same exact instance all the time, with no possibility to change the state,  there is no reason to create multiple instances and waste memory. Instead, it’s more efficient to return the same instance (Like we are doing above)

A good example of where singleton design pattern can be used, is when you are trying to create a database connection. You don’t want to create a brand new database connection every time you fire a query. That would be very inefficient and would cost the performance.

However, if you use singleton pattern, you’d use the same connection object for every database request. There by, you will not only save the time it takes to create the instance or to creating the connection, but also precious runtime memory.

Another example of where singleton design pattern can be used is when you implement ‘logging’ mechanism in your application. You’d create one instance of logger and you’d use the same instance throughout your application to log messages.

Convinced? Sounds good?

 

When not to use Singleton Design Pattern?

As you might have guessed by now, we should not use singlton design pattern if you object holds a state. But, have you ever though why?? Think about it!

Imagine (Just for the sake of this example) that we have 3 databases d1,d2,d3 and there are 3 threads, t1, t2, t3. Lets say

t1 want’s to connect to d1

t2 want’s to connect to d2

t3 want’s to connect to d3

Also imagine that we have singleton class (Like in our previous section) that connects to a database. But this time, we will have a property that says ‘serverIP’. Each thread has to pass the server IP as the constructor argument while creating the instance of this class. So that a connection would be established using that IP.

Here’s the problem. Let’s say t1 sent the IP ‘2.2.2.2’, but before the connection logic is executed, thread t2 enters and changes the IP of say ‘3.3.3.3’..

What just happened? DISASTER!! Now both the threads will connect to ‘3.3.3.3’ ip!! Which is clearly not what we intend to do.

So, the solution in this case is simple to not use singleton design pattern and use a regular class.

An example was demonstrated in the above video.

 

Understanding Lazy vs Eager loading

So far, we are creating the singleton instances ‘On Demand’. I.e.. when you call the ‘getInstance()’ method. Not before it. This is called Lazy loading.

It’s kind of similar to you not waking up in the morning, unless someone wake you up! Or you not doing the work, unless you are asked to do.

But the opposite of Lazy loading is Eager loading. Where the instance would be created up front (Before even requesting for it) and is up for grabs.

Kind of similar to you preparing the dish before customer placed the order. Because you already knew, somebody is going to need it, and save preparation time when ordered (Nice example 😇. I deserve your ‘like’ and ‘share’ of this article 😕).

Here is the tweaked version of our singleton example, that loads the instance in Eager manner. We moved he instance creation part to a static block (Core java concept! Seriously, core java is the basis for everything. If you want to learn core java, I recommended a course above at the start of the page)

public class EagerExample {

	private static EagerExample instance;

	private EagerExample() {

	}

	static {
		instance = new EagerExample();
	}

	public static EagerExample getInstance() {
		return instance;
	}
	
	public void businessLogic(String message) {
		System.out.println("Executing Business logic..." + message);
	}
}

 

Singleton Beans in Spring Framework

By default all the beans in Spring that you define in config files are Sington in nature.

But, you have to be careful to not introduce any properties in that spring beans. In case ff you do, you must at least know what you are doing.

Alternatively, if you can configure a ‘Prototype’ bean (The opposite of Singeton). In which case, there would be multiple instances of same bean.

This is demonstrated well in the video tutorial above.

Also, all the beans are by default loaded in Eager manner. That means, all the singleton instances are created, right when the container loads. This is good for our database connection example we considered earlier.

If you want them to load in ‘Lazy’ manner, you can configure that while configuring beans. You can even go ahead and make Lazy loading the default behavior.

For example, if you are using XML configuration to define beans,  you can add the following attribute in the main tag ‘default-lazy-init=”true”‘ and you are good to go! You can also use annotation ‘@Lazy’ if you wish.

 

Source Code

Below is the example code for singleton in spring (Only includes some key files). If you want to download complete project, GitHub link is provided in the end and you check the video tutorial for detailed walk through!

package org.company;

public class SampleBean {

	private AnotherBean anotherBean;

	public SampleBean() {
	}

	public SampleBean(AnotherBean anotherBean) {

		System.out.println("Constructor of SampleBean Called!");
		this.anotherBean = anotherBean;
	}

	public void sampleMethod(String message) {
		anotherBean.displayMessage(message);
	}
}

 

package org.company;

import java.io.IOException;

import org.company.config.JavaConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyApp {

	public static void main(String[] args) throws IOException {

		// Bean config using XML
		//ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");

		// Bean config using Java
		ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
		System.out.println("Requesting for a Bean..");

		System.out.println("Hashcodes..");
		new Thread(() -> System.out.println(((SampleBean) context.getBean("sampleBean")).hashCode())).start();
		new Thread(() -> System.out.println(((SampleBean) context.getBean("sampleBean")).hashCode())).start();
		new Thread(() -> System.out.println(((SampleBean) context.getBean("sampleBean")).hashCode())).start();
		new Thread(() -> System.out.println(((SampleBean) context.getBean("sampleBean")).hashCode())).start();
		
		System.out.println("Executing behaviour..");
		new Thread(() -> ((SampleBean) context.getBean("sampleBean")).sampleMethod("Message from T1")).start();
		new Thread(() -> ((SampleBean) context.getBean("sampleBean")).sampleMethod("Message from T2")).start();
		new Thread(() -> ((SampleBean) context.getBean("sampleBean")).sampleMethod("Message from T3")).start();
		new Thread(() -> ((SampleBean) context.getBean("sampleBean")).sampleMethod("Message from T4")).start();
	}

}

 

package org.company.config;

import org.company.AnotherBean;
import org.company.SampleBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Lazy
@Configuration
public class JavaConfig {

	@Lazy(false)
	@Bean
	public AnotherBean anotherBean() {
		return new AnotherBean();
	}
	

	@Bean
	public SampleBean sampleBean(AnotherBean anotherBean) {
		return new SampleBean(anotherBean);
	}
}

Good luck!

Leave a Comment