e-Zest members share technology ideas to foster digital transformation.

Spring Singleton and Java Singleton Pattern

Written by Vishwanath Mathapati | Jan 22, 2013 1:44:53 PM

I thought of writing this blog while studying the difference between Singleton pattern and Spring Framework Singleton scope for Bean/POJO. As the default scope for Bean within Spring container is singleton, hence while using Spring's ApplicationContext and BeanFactory we will be getting a single instance to work with. Hence we may be using the Bean instance from the BeanFactory which is singleton in nature, but it is quite different from the Singleton Pattern.

As Singleton Pattern will be looking at an instance that is single or unique per class and per class loader level. Although Spring Framework Bean singleton scope is single in nature but it is within Spring Framework container boundary/level. So for a particular Spring ApplicationContext and BeanFactory, there could be a single Bean instance for a particular Bean with a unique id.

So let us explore more about this with the help of the following example, where I will be creating a single application context and BeanFactory using ClassPathXmlApplicationContextAPI from Spring Framework by passing this example test.xml configuration file as argument parameter.

Then I retrieve a Bean instance from the Spring BeanFactory using a Spring Bean id and then set value for the instance variable of this Spring Bean instance. Second time while fetching the Spring Bean with the same Bean id (as that of previous Bean id) it returns the same Bean instance like that of the first time.

As the Spring container by default manages the singleton scope for this Bean, the value set in the first case has to be retained in the second case as well.

package com.myspring.mvc;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringMainClass1 {
    public SpringMainClass1() {
        try{
	    ApplicationContext appContext =
	        new ClassPathXmlApplicationContext("test.xml");
	    BeanFactory factory = appContext;
	    //Retrieving bean from the bean factory.
	    //Bean id as "one"
	    One one1 = (One)factory.getBean("one");
	    one1.setName("test name");

	    //Bean id as "one"
	    One one2 = (One)factory.getBean("one");
	    System.out.println("Name from the singleton bean :"+one2.getName());
	} catch(Exception ex) {
	    ex.printStackTrace();
	}
    }
    public static void main(String args[]) {
        new SpringMainClass1();
    }
}

In the above code, Bean instance from Spring container is fetched and then some random name value is set to this instance. While in the next step, the Bean instance is fetched from Spring container using the same Bean id. The value for the second Bean is showing the value set previously in the first Bean. This shows that both these instances are the same, thus can be treated as singleton from Spring's singleton scope.

Let us modify the above example, to see how two instances of ApplicationContext and BeanFactory of Spring are fetching the same Bean from the Spring containers although they are totally different instances. But now there is a difference being observed, the returned value is null, not the original value that is set in the first case.

package com.myspring.mvc;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringMainClass2 {

    public SpringMainClass2() {
        try {
	ApplicationContext appContext = new ClassPathXmlApplicationContext("test.xml");
	BeanFactory factory = appContext;
	// Retrieving bean from the bean factory.
	One one1 = (One) factory.getBean("one");
	one1.setName("test name");

	ApplicationContext appContextNew = new ClassPathXmlApplicationContext("test.xml");
	BeanFactory factoryNew = appContextNew;

	One one2 = (One) factoryNew.getBean("one");
	System.out.println("Name from the singleton bean :"+ one2.getName());
    } catch (Exception ex) {
	ex.printStackTrace();
    }
}

    public static void main(String args[]) {
        new SpringMainClass2();
    }
}

The above modified code uses two different Spring Context and so we have two different Bean instances, while one Context taking the setter value and the other Context returning null value. Code for the Bean in this example, is as follows:

package com.myspring.mvc;

public class One
{
    private String name;
    public void setName(String arg) {
        name = arg;
    }
    public String getName() {
        return name;
    }
}

The Spring configuration file is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
  "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean id="one" class="com.myspring.mvc.One">
  </bean>
</beans>

The above test example is executed considering that the Spring related JARs are available in Eclipse Spring project.