Spring Core - Bean scopes (Prototype vs Singleton)

In this post, we will discuss about various bean scopes and their differences.

Bean scopes

There are seven bean scopes Spring supports out of which five are only available if your ApplicationContext is web-aware.

# Scope Explanation
1 singleton There will be single object of the bean per Spring IoC Container (Default).
2 prototype Scope beans to any number of object instances. Every time you get object of prototype bean from context, it will be brand new.
3 request Scope of the bean definition mapped to the lifecycle of HTTP Request. This is only available web-aware ApplicationContext.
4 session Scope of the bean definition mapped to the lifecycle of HTTP session. This is only available to web-aware ApplicationContext.
5 globalSession Scope of the bean definition mapped to the lifecycle of HTTP session usually used within Portlet context. This is only available to web-aware ApplicationContext.
6 application Scope of the bean definition mapped to the ServletContext. This is only available to web-aware ApplicationContext.
7 websocket Scope of the bean mapped to the lifecycle of Websocket. This is only available to web-aware ApplicationContext.

Singleton Vs Prototype

Let's see a example which shows the difference between Singleton and Prototype scope for bean.

public class Dictionary {
  private List words;
  public Dictionary() {
    words = new ArrayList<>();
  }
 
  public void addWord(String word) {
    this.words.add(word);
  }
 
  public int totalWords() {
    return this.words.size();
  }
 
  @Override
  public String toString() {
    return words.toString();
  }
}

We first defined a class Dictionary.

Singleton scope

There will be only one shared instance of singleton bean per context and all request for that bean definition will end up returning the same object by the container.

@Configuration
public class ScopeConfig {
  @Bean(name = "singletonDictionary")
  @Scope("singleton") 
  //you can omit the scope by default it is singleton
  Dictionary singletonDictionary() {
    return new Dictionary();
  }
}

We created a configuration class ScopeConfig. We created a bean Dictionary. @Scope annotation is used to mark the scope of the bean to singleton. If we don't define any scope then by default it is considered singleton scoped bean.

public class App {
  private static final Logger logger = Logger.getLogger(App.class.getName());
  public static void main(String[] args) {
    try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class);) {
      Dictionary singletonDictionary = context.getBean("singletonDictionary", Dictionary.class);
      logger.info("Singleton Scope example starts");
      singletonDictionary.addWord("Give");
      singletonDictionary.addWord("Take");
      int totalWords = singletonDictionary.totalWords();
      logger.info("Need to have two words. Total words are : " + totalWords);
      logger.info(singletonDictionary.toString());
      singletonDictionary = context.getBean("singletonDictionary", Dictionary.class);
      logger.info("Need to have two words. Total words are : " + totalWords);
      logger.info(singletonDictionary.toString());
      logger.info("Singleton Scope example ends");
    }
  }
}

When we run above snippet, it will generate output like below.

Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Singleton Scope example starts
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Need to have two words. Total words are : 2
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: [Give, Take]
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Need to have two words. Total words are : 2
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: [Give, Take]
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Singleton Scope example ends

From output, we can analyse that when we got object of singletonDictionary again from context, it contained the previous added values.

Prototype scope

Prototype scope of bean results in the creation of a new bean instance every time a request for that specific bean is made.

@Configuration
public class ScopeConfig {
  @Bean(name = "prototypeDictionary")
  @Scope("prototype") 
  Dictionary prototypeDictionary() {
    return new Dictionary();
  }
}

We created a configuration class ScopeConfig. We defined a bean prototypeDictionary. We used @Scope annotation to mark its scope as prototype.

public class App {
  private static final Logger logger = Logger.getLogger(App.class.getName());
  public static void main(String[] args) {
    try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ScopeConfig.class);) {
      Dictionary prototypeDictionary = context.getBean("prototypeDictionary", Dictionary.class);
      logger.info("Prototype scope example starts");
      prototypeDictionary.addWord("Give 2");
      prototypeDictionary.addWord("Take 2");
      logger.info("Need to have two words. Total words are: " + prototypeDictionary.totalWords());
      logger.info(prototypeDictionary.toString());
      prototypeDictionary = context.getBean("prototypeDictionary", Dictionary.class);
      logger.info("zero word count. Total words are: " + prototypeDictionary.totalWords());
      logger.info(prototypeDictionary.toString());
    }
  }
}

The above code snippet generated below output.

Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Prototype scope example starts
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: Need to have two words. Total words are: 2
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: [Give 2, Take 2]
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: zero word count. Total words are: 0
Feb 12, 2017 11:50:18 PM com.gauravbytes.springbeanscope.App main
INFO: []

From the output logs, you can clearly see that when we got prototypeDictionary object again from context then it returned a new object and there was no previously added words in it.

When to use Singleton and Prototype

Use prototype scope for all stateful beans and singleton scope for stateless beans.

This is all about bean scopes. I hope you find this post informative. You can find the example code on Github.

1 comment :

  1. Good start. I think you may wanna quote real life examples of when to use singleton or prototype. And may be the problems which me arise if we don't pay heed to this.

    ReplyDelete