Monday 12 November 2012

Spring singleton beans vs Singleton design pattern

Spring singleton beans vs Singleton design pattern


Singleton beans in Spring and classes based on Singleton design pattern are quite different.

Singleton pattern ensures that one and only one instance of a particular class will ever be created per classloader where as the scope of a Spring singleton bean is described as 'per container per bean'.
Singleton scope in Spring means that this bean will be instantiated only once by Spring. Spring container merely returns the same instance again and again for subsequent calls to get the bean.

The below example shows that repeated calls to get the ‘bloggerService’ bean returns the same bean again and again.

Defining a Singleton scoped bean in spring application context (appContext.xml)

 <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-2.5.xsd">  
   
    <bean id="bloggerService" 
               class="in.blogspot.javasampleprogram.BloggerService" />  
 </beans>  

 package in.blogspot.javasampleprogram;  
 import org.springframework.context.ApplicationContext;  
 import org.springframework.context.support.ClassPathXmlApplicationContext;  

 class BloggerService   
 {  
      String blogName;  
      public String getBlogName() {  
           return blogName;  
      }  
      public void setBlogName(String blogName) {  
           this.blogName = blogName;  
      }  
 }  
 public class AppContextTest {  
      public static void main(String[] args) {  
           ApplicationContext context1 = new ClassPathXmlApplicationContext(
                  new String[] { "in/blogspot/javasampleprogram/appContext.xml" });  

           BloggerService custA = (BloggerService) context1.getBean("bloggerService");  
           custA.setBlogName("http://java-sample-program.blogspot.in/");  
           System.out.println("blog name: " + custA.getBlogName()); 
           
           // returns the same bean again  
           BloggerService custB = (BloggerService) context1.getBean("bloggerService");  
           System.out.println("blog name: " + custB.getBlogName());  
      }  
 }  
Console Output:
blog  name: http://java-sample-program.blogspot.in/

Now if we load the context again and then try to fetch the ‘bloggerService’ we will get a new bean. So even though the classloader of both context1 and context2 are same, there will be two separate BloggerService instances created by each context.
 package in.blogspot.javasampleprogram;  
 import org.springframework.context.ApplicationContext;  
 import org.springframework.context.support.ClassPathXmlApplicationContext;  

 class BloggerService   
 {  
      String blogName;  
      public String getBlogName() {  
           return blogName;  
      }  
      public void setBlogName(String blogName) {  
           this.blogName = blogName;  
      }  
 }  
 public class AppContextTest {  
      public static void main(String[] args) {  
           ApplicationContext context1 = new ClassPathXmlApplicationContext(
                   new String[] { "in/blogspot/javasampleprogram/appContext.xml" });  
           
           BloggerService custA = (BloggerService) context1.getBean("bloggerService");  
           custA.setBlogName("http://java-sample-program.blogspot.in/");  
           System.out.println("blog name: " + custA.getBlogName()); 
  
           // returns the same bean again  
           BloggerService custB = (BloggerService) context1.getBean("bloggerService");  
           System.out.println("blog name: " + custB.getBlogName()); 
  
           // reloading the application context  
           ApplicationContext context2 = new ClassPathXmlApplicationContext(
                   new String[] { "in/blogspot/javasampleprogram/appContext.xml" });  
           
           custA = (BloggerService) context2.getBean("bloggerService");  
           System.out.println("blog name: " + custA.getBlogName()); // print null  
           
          // both context1 and context2 have same classloaders
          System.out.println("context1 classloader: "+context1.getClassLoader());
          System.out.println("context2 classloader: "+context2.getClassLoader());  
      }  
 }  
Console Output:
blog  name: null
context1 classloader: sun.misc.Launcher$AppClassLoader@53372a1a 
context2 classloader: sun.misc.Launcher$AppClassLoader@53372a1a

To read more about Spring bean scopes, please go through the below links:-
Spring Bean Scopes

To read more about Singleton design patterns:-

4 comments:

  1. nice.. can u please help me to download all spring jars..

    ReplyDelete
  2. Please use the following jars:

    org.springframework.asm-3.1.3.RELEASE.jar
    org.springframework.beans-3.1.3.RELEASE.jar
    org.springframework.context-3.1.3.RELEASE.jar
    org.springframework.core-3.1.3.RELEASE.jar
    org.springframework.expression-3.1.3.RELEASE.jar
    com.springsource.org.apache.commons.logging-1.1.1.jar

    ReplyDelete
  3. Singleton pattern is described at per class loader level.
    Singleton bean scope is per spring container.

    http://www.javabench.in/2012/04/difference-between-singleton-design.html

    ReplyDelete

/* */