Singleton pattern is scoped by per Java class.
Singleton bean scope is scoped by per spring container.
In singleton pattern, Java considers a class as singleton if it cannot create more than one instance of that class within a given class loader whereas spring considers a bean class as singleton scope if it cannot create more than one instance of bean class within a given Applicationcontext(container).
Spring container will create exactly one instance of the defined bean. This single instance will be stored in a cache of singleton bean and same instance will be returned in all subsequent requests.
Very important point to discuss here is what happens if there are multiple containers and same class loader.Lets create one example to understand this.
In below Spring example, we have created two applicationContext object( in MainApp class) which are used to load the ‘student bean'(Student class). When the same bean is again loaded with different application context object then it will return ‘null’ as bean name because scope of bean is limited within an application context.
MainApp.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 |
package com.j2eereference; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; public class MainApp { public static void main(String[] args) { ApplicationContext factory = new ClassPathXmlApplicationContext( new String[] { "Applicationcontext.xml"}); Student student1 = (Student) factory.getBean("student"); student1.setName("Shikha"); System.out.println("Bean name 1 : " + student1.getName()); ApplicationContext factory2 = new ClassPathXmlApplicationContext( new String[] { "Applicationcontext.xml"}); Student student2= (Student) factory2.getBean("student"); System.out.println("Bean name in case of new applicationcontext This Time : " + student2.getName()); System.out.println("context classloader: "+factory.getClassLoader()); System.out.println("newContext classloader: "+factory2.getClassLoader()); } } |
Application context : ApplicationContext provides context information and contains definition of beans.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="student" class="com.j2eereference.Student" scope="singleton" > </bean> </beans> |
Student.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 |
package com.j2eereference; import java.util.List; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.config.BeanPostProcessor; public class Student { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } } |
OutPut:
org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@179d3b25: startup date [Tue May 16 16:18:19 IST 2017]; root of context hierarchy
May 16, 2017 4:18:19 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [Applicationcontext.xml]
Bean name 1 : Shikha
May 16, 2017 4:18:20 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6a400542: startup date [Tue May 16 16:18:20 IST 2017]; root of context hierarchy
May 16, 2017 4:18:20 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [Applicationcontext.xml]
Bean name 2 This Time : null
context classloader: sun.misc.Launcher$AppClassLoader@73d16e93
newContext classloader: sun.misc.Launcher$AppClassLoader@73d16e93
If you want to return same instance of class in in every subsequent request then comment lines in which we created second ApplicationContext as given in below code
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.j2eerefernce; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; public class MainApp { public static void main(String[] args) { ApplicationContext factory = new ClassPathXmlApplicationContext( new String[] { "Applicationcontext.xml"}); Student student1 = (Student) factory.getBean("student"); student1.setName("Shikha"); System.out.println("Bean name 1 : " + student1.getName()); <strong> // ApplicationContext factory2 = new ClassPathXmlApplicationContext( new String[] // { "Applicationcontext.xml"});</strong> Student student2= (Student) factory.getBean("student"); System.out.println("Bean name this Time : " + student2.getName()); System.out.println("context classloader: "+factory.getClassLoader()); // System.out.println("newContext classloader: "+factory2.getClassLoader()); } } |
Now run the MainApp , you will get OutPut as
May 16, 2017 4:43:33 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@179d3b25: startup date [Tue May 16 16:43:33 IST 2017]; root of context hierarchy
May 16, 2017 4:43:33 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [Applicationcontext.xml]
Bean name 1 : Shikha
Bean name this Time : Shikha
context classloader: sun.misc.Launcher$AppClassLoader@73d16e93
Please refer injecting singleton class with Spring to know more about singleton bean creation.