Injecting singleton class with spring
There are some differences between Singleton as a design pattern and Spring’s singleton scope. Singleton as a design pattern will ensure that you have only one object of class defined per Class Loader. But in case of Spring’s singleton scope ,spring will create one instance per Spring Context.
First lets see the common issue we face when we inject singleton class properly. Here in this example we have a singleton class as below and we have configured the same bean in two different configuration files,spring1.xml and spring2.xml .
Singleton.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.j2eereference.spring; public class Singleton { private static Singleton singleton; String name="ABC"; private Singleton(){ System.out.println("Inside constructor "); } public static Singleton getInstance(){ if(singleton == null){ return new Singleton(); } else return singleton; } public void printInfo(){ System.out.println("Name is : " +name); } public void setName(String name) { this.name = name; } } |
Spring1.xml
1 2 3 4 5 6 7 |
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="singleton" class="com.j2eereference.spring.Singleton"/> </beans> |
spring2.xml
1 2 3 4 5 6 7 |
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="singleton" class="com.j2eereference.spring.Singleton"/> </beans> |
Demo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.j2eereference.spring; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringDemo { public static void main(String[] args) { AbstractApplicationContext context = new ClassPathXmlApplicationContext( "spring1.xml"); AbstractApplicationContext context2 = new ClassPathXmlApplicationContext( "spring2.xml"); Singleton singleton= (Singleton)context.getBean("singleton"); singleton.setName("XYZ"); singleton.printInfo(); Singleton singleton2= (Singleton)context2.getBean("singleton"); singleton2.printInfo(); } } |
output
Jun 18, 2015 11:56:42 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5c07612a: startup date [Thu Jun 18 11:56:42 IST 2015]; root of context hierarchy
Jun 18, 2015 11:56:42 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring1.xml]
Inside constructor
Jun 18, 2015 11:56:42 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@555fbf35: startup date [Thu Jun 18 11:56:42 IST 2015]; root of context hierarchy
Jun 18, 2015 11:56:42 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring2.xml]
Inside constructor
Name is : XYZ
Name is : ABC
Here you can notice that spring has created two different objects when it load the spring.xml files .
If you want to get only one instance of a particular class irrespective of multiple spring contexts ,we can make use of factory-method attribute as below.
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="singleton" class="com.j2eereference.spring.Singleton" factory-method="getInstance"> </bean> </beans> |
If you run the same Demo.java with the above spring configuration you will get the below output
Output
Jun 18, 2015 12:01:40 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@498ab963: startup date [Thu Jun 18 12:01:40 IST 2015]; root of context hierarchy
Jun 18, 2015 12:01:40 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring1.xml]
Inside constructor
Jun 18, 2015 12:01:40 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@de5770f: startup date [Thu Jun 18 12:01:40 IST 2015]; root of context hierarchy
Jun 18, 2015 12:01:40 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring2.xml]
Name is : XYZ
Name is : XYZ
Now spring created only one object .
Leave a Reply