Comprehensive Guide to Understand Spring Bean Scopes

Written by bumblebee | Published 2021/05/03
Tech Story Tags: spring | spring-framework | learn-spring-framework | java | backend | model-view-controller | spring-bean-scopes | hackernoon-top-story

TLDR An object that is instantiated, gathered, and otherwise managed by a Spring container is called a bean. The configuration metadata that you provide to the container is used to build these beans. Spring framework was first released under the Apache 2.0 license in June 2003. It is the most common application development platform for enterprise Java. It is used by millions of users across the globe to build high-performing, conveniently verifiable, and reusable code. The default scope of a bean is singleton. Two of them are available for both IoC and Spring-MVC containers while the rest three are only usable in the context of web-aware Spring Application Context.via the TL;DR App

Written by Rod Johnson, Spring framework was first released under the Apache 2.0 license in June 2003. It is the most common application development platform for enterprise Java. This open-source Java platform is used by millions of users across the globe to build high-performing, conveniently verifiable, and reusable code.
What is Spring Bean?
An object that is instantiated, gathered, and otherwise managed by a Spring IoC container is called a bean. The configuration metadata that you provide to the container is used to build these beans. The configuration metadata that you provide to the container is used to build these beans. The configuration metadata contained in the bean specification is required for the container to know how to make a bean, details of bean’s lifespan and timeline and its dependencies.
Bean Scopes in Spring:
The scope of a bean corresponds to the lifecycle of a bean, which includes when the object is instantiated, how long it lives, and how many objects are made for that bean over time. Regulated by the spring container, it basically manages the bean instance formation.
Five different scopes for a bean are included in the spring framework. Two of them are available for both IoC and Spring-MVC containers while the rest three are only usable in the context of web-aware Spring ApplicationContext. The following are the five different scopes for a bean:
  • Singleton: Per Spring IoC container, only one instance of a single bean definition will be generated, and the same object will be shared for each request made for that bean. The default scope of a bean is singleton.
  • Prototype: Each time a request is made for a single bean definition, a new instance will be generated.
  • Request: Each time an HTTP request for a single bean definition is made, a new instance is generated for that bean. However, this is only usable when using a web-aware Spring ApplicationContext.
  • Session: A single bean definition is scoped to an HTTP Session's lifecycle. However, this is only usable when using a web-aware Spring ApplicationContext.
  • Global-Session: A single bean definition is scoped to an global HTTP Session's lifecycle. However, this is only usable when using a web-aware Spring ApplicationContext.
Singleton Scope:
If the bean's scope is singleton, only one object of that bean will be created per Spring IoC container, and that object will be shared across all requests, i.e., the same instance is returned each time it is injected. When a bean's scope is declared as singleton, the spring IOC container first checks if an object of that bean has already been generated before making a new request for it. The IOC container returns the same instance if it has already been created; otherwise, it generates a new instance of that bean only on the first request.
Example:
First of all, we create a bean in our example.
// JAVA CODE
package bean;
public class Sample{
    public int value;
  
    //A setter method to set the value
    public void setValue(int data)
    {
        this.value = data;
    }
  
    //A getter method to get the value
    public String getValue()
    {
        return value;
    }
}
Then we write the configuration file “SampleXML.xml” and configure the bean that we just created.
<!-- XML CODE -->
<!DOCTYPE beans PUBLIC
     "-//SPRING//DTD BEAN 2.0//EN"
     "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
     < bean
         id = "id1"
         class= "bean.Sample"
         scope = "singleton" / >
</beans>
Then we write a driver class “User.java” which can request the above bean.
// JAVA CODE
package driver;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import bean.Sample;
  
public class User {
  
    public static void main(String[] args)
    {
        // Loading the XML configuration file
        ApplicationContext appContext = new ClassPathXmlApplicationContext( "resources/SampleXML.xml");
        Sample obj1 = (Sample)appContext.getBean("id1");
        obj1.setValue(10);
        System.out.println("The value for object obj1 is :" + obj1.getValue());
        Sample obj2 = (Sample)appContext.getBean("id1");
        System.out.println("The value for object obj2 is :" + obj2.getValue());
        if(obj1 == obj2)
        {
            System.out.println("Both obj1 and obj2 are pointing to the same object.");
        }
        else
        {
            System.out.println("obj1 and obj2 are different objects.");
        }
        System.out.println("The address of object obj1 is :" + obj1);
        System.out.println("The address of object obj2 is :" + obj2);

    }
}
Output:
The value for object obj1 is :10
The value for object obj2 is:10
Both obj1 and obj2 are pointing to the same object.
The address of object obj1 is:bean.Sample@564213rt
The address of object obj2 is :bean.Sample@564213rt
Explanation:
We can clearly see that since the scope property in the bean was set to “singleton”, only one instance of the bean has been instantiated and this is shared amongst all the requests made by the user.
Prototype Scope:
If the scope is prototype, the spring IOC container will generate a new object of that bean whenever a request for that bean is created. A request to the bean instance can be generated programmatically by using getBean() method or via XML for Dependency Injection of secondary form.
Example:
Again, we first create the bean in our example.
// JAVA CODE
package bean;
public class Sample{
    public int value;
  
    //A setter method to set the value
    public void setValue(int data)
    {
        this.value = data;
    }
  
    //A getter method to get the value
    public String getValue()
    {
        return value;
    }
}
Then we write the configuration file “SampleXML.xml” and configure the bean that we just created.
<!-- XML CODE -->
<!DOCTYPE beans PUBLIC
     "-//SPRING//DTD BEAN 2.0//EN"
     "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
     < bean
         id = "id1"
         class= "bean.Sample"
         scope = "prototype" / >
</beans>
Then we write a driver class “User.java” which can request the above bean..
// JAVA CODE
package driver;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import bean.Sample;
  
public class User {
  
    public static void main(String[] args)
    {
        // Loading the XML configuration file
        ApplicationContext appContext = new ClassPathXmlApplicationContext( "resources/SampleXML.xml");
        Sample obj1 = (Sample)appContext.getBean("id1");
        obj1.setValue(10);
        System.out.println("The value for object obj1 is :" + obj1.getValue());
        Sample obj2 = (Sample)appContext.getBean("id1");
        System.out.println("The value for object obj2 is :" + obj2.getValue());
        if(obj1 == obj2)
        {
            System.out.println("Both obj1 and obj2 are pointing to the same object.");
        }
        else
        {
            System.out.println("obj1 and obj2 are different objects.");
        }
        System.out.println("The address of object obj1 is :" + obj1);
        System.out.println("The address of object obj2 is :" + obj2);

    }
}
Output:
The value for object obj1 is: 10
The value for object obj2 is: null
obj1 and obj2 are different objects.
The address of object obj1 is: bean.Sample@564213rt
The address of object obj2 is: bean.Sample@4361ae3w
Explanation:
We can clearly see that since the scope property in the bean was set to “prototype”, a new instance of the bean has been instantiated whenever a new request is made by the user.

Interview Questions on Spring Bean:

You may know more about this framework and go through some important spring interview questions here: link
Q1. Briefly explain the three ways of implementing the lifecycle of a bean.
Ans. The three ways of implementing the lifecycle of a bean are:
  • Through XML: In this technique, we must register custom init() and destroy() methods for a bean in the Spring XML configuration file when defining the bean.
  • Using Programmatic Approach: To give the generated bean, the ability to call a custom init() method on the start of a spring container and a custom destroy() method on the close of the container, we must incorporate our bean with two interfaces, InitializingBean and DisposableBean, and override the afterPropertiesSet() and destroy() methods. The afterPropertiesSet() method is called when the container first starts and the bean is formed, while the destroy() method is called when the container is closed.
  • Using Annotation: To give the generated bean the ability to call a custom init() method on a spring container's startup and to call a custom destroy() method on the container's closure, we need to annotate the init() method with the @PostConstruct annotation and the destroy() method with the @PreDestroy annotation.
Q2. What are inner beans in spring?
Ans. Only when a bean is used as a property of some other bean can it be deemed as an inner bean. Spring's XML-based configuration metadata allows you to define a bean by using the bean> element inside the property> or constructor-arg> elements. Inner beans are always anonymous, and their scope is always prototype.
Q3. What are stateful and stateless beans?
Ans. Stateless beans are singleton beans that are initialised only once. They possess a shared state.
Beans that can carry state are known as stateful beans (instance variables). Any time an object is needed, these beans are generated.
Q4. List the differences between singleton scope and prototype scope.
Singleton:
  • Only one object is generated for a single bean definition per Spring IoC container. Same object is shared for each request made for that bean.
  • The scope of a bean is singleton by default. As a result, we don't have to specifically declare a bean as a singleton.
  • For stateless beans, singleton scope is used.
Prototype:
  • A new object is generated for a single bean definition each time a request is made for that bean. For every new request, a new object is generated.
  • Since scope is not defaulted to prototype, you must specifically declare the scope of a being as prototype.
  • For stateful beans, prototype scope is used.
Q5. What is bean wiring?
Ans. Bean wiring is the process of combining beans inside a Spring container. When wiring beans, the Spring container needs to learn what beans are required and how the container can use dependency injection to connect the beans.
Q6. What are BeanPostProcessor beans?
Ans. BPP bean is a unique type of bean that is generated before any other bean and interacts with the newly created ones.
Q7. What is the work of a Spring bean configuration file?
Ans. All of the beans that will be initialised by Spring Context are defined by the Spring bean configuration file. When a Spring ApplicationContext object is generated, it reads the spring bean xml file and initializes all of the beans. If the context has been initialized, it can be used to obtain various bean instances.
Q8. Discuss auto-wiring and its different modes.
Ans. Spring includes a feature that allows you to automatically detect the relationships between different beans. All of the bean dependencies can be declared in the Spring configuration file. As a result, Spring will use the BeanFactory to determine the dependencies among all of the beans in use. The Spring container will automatically wire relationships between cooperating beans. That is, by inspecting the contents of the BeanFactory, you can have Spring automatically resolve collaborators for your bean.
Different modes of autowiring are:
  • no: This is the default setting, so no autowiring is allowed. Wiring should be done with explicit bean references.
  • byName: It injects the object dependency based on the bean's name. It matches and connects its properties to the beans in the XML file with the same names.
  • byType: It injects object dependencies based on their type. If the form of a property matches exactly one of the beans’ names in the XML file, it is matched and wired.
  • constructor: It injects the dependency by invoking the class's constructor. It has a vast range of configurations to choose from.
  • autodetect: The container attempts to connect using autowire by constructor first, then autowire by byType if that fails.
Q9. What are the drawbacks of autowiring?
Ans. Following are the drawbacks of autowiring:
  • Properties like primitives, strings, and classes cannot be autowired.
  • Since autowiring is less accurate, it is often desirable to use explicit wiring.
  • Use of <constructor-arg> and <property> settings to specify dependencies will override autowiring.
Q10. Why is spring bean with default scope not thread safe?
Ans. Spring bean's default scope is singleton, which means there will only be one instance per context. Inconsistent data would result from having a bean class level variable that every thread can update. As a result, spring beans are not thread-safe in default mode.
Q11. What are the different ways to configure a Java class as a spring bean?
Ans. There are three ways to set up a class as a Spring Bean:
The most common configuration is XML Configuration. The bean element tag is used to configure a Spring Bean in an xml context file.
The @Bean annotation can be used to configure a Spring bean using Java Based Configuration. This annotation is used to initialize a spring bean with @Configuration groups.
@Component, @Service, @Repository, and @Controller annotations with classes allow Annotation Based Configuration to configure them as spring beans. To search for these classes, we'd need to have a base package location.
Q12. If an inner bean defines an id, can we access it from a spring container using that id?
Ans. No, an inner bean cannot be fetched from a spring container even if the id attribute is defined. getBean("theInnerId") fails with NoSuchBeanDefinitionException.
Q13. Discuss Spring bean inheritance.
Ans. By determining parent and child beans, a spring bean may show inheritance actions. The abstract attribute value of true is used to configure the parent beans. The parent attribute on the bean tag, with the parent bean id as its value, can be used to configure a child bean.
A parent definition's configuration data is passed down to a child bean definition. The child concept has the ability to override a few values and add more as required.
While Spring Bean definition inheritance is not the same as Java class inheritance, the concepts are similar. You can use a parent bean specification as a reference, and other child beans can acquire the parent bean's required configuration.
Q14. Explain Bean Definition Template in Spring Framework.
Ans. Bean Definition Template, also known as parent beans, are used to describe common bean definitions that are shared by other child beans without having to rewrite them. When creating a Bean Definition Template, the class attribute should be left blank and the abstract attribute should be set to valid. Since it is incomplete and clearly labelled as abstract, the parent bean cannot be initialised on its own.
Q15. When is a singleton and a prototype bean garbage collected? 
Ans. When the Spring container starts, singleton beans are made, and when the Spring container ceases, they are destroyed. The explanation for this is that the spring container retains a reference to it at all times, even if it is manually referenced elsewhere in your code.
Spring just takes care of the prototype bean's development and configuration; after that, it's up to the consumer (or the JVM) to do whatever is needed. Internal references to prototype beans are not kept by Spring.

Written by bumblebee | Tech Blogger and Content Marketer
Published by HackerNoon on 2021/05/03