The bean's scope

Spring provides us with beans after instantiating and configuring them. Spring Container manages objects. This means that any object can refer to any other object from Spring Container using the bean's ID, and Spring Container provides an instance of the requesting object.

When we start Spring Container, ApplicationContext reads the Spring configuration, file looks for all bean definitions available there, and then initializes beans before any call to the getBean() method.

During initialization, ApplicationContext itself has initialized all the Spring beans configured in Spring XML. When another object makes a call to the getBean() method, ApplicationContext returns the same reference of bean that has already been initialized. This is the default behavior of beans.

This leads to the concept of a bean's scope. We can choose the number of instances of beans depending on the scope. There are different scopes in which a bean can be configured. The <bean> tag has a scope attribute that is used to configure the scope of the bean. There are different bean scopes in Spring, such as singleton, prototype, request, session, and global session. We will understand each session one by one.

Let's understand this by considering the following example, where we have the EmployeeService interface, EmployeeServiceImpl class, and PayrollSystem class with the main() method.

In the EmployeeService.java interface, you'll find the following code:

package org.packt.Spring.chapter2.beanscope;

public interface EmployeeService {
   void setMessage(String message);
   String getMessage();
}

In the preceding code snippet, the EmployeeService interface declares two methods.

The following are the contents of the EmployeeServiceImpl.java class:

package org.packt.Spring.chapter2.beanscope;

import org.springframework.beans.factory.InitializingBean;

public class EmployeeServiceImp implements EmployeeService {

   private String message;

   @Override
   public void setMessage(String message) {
         this.message = message;
   }

   @Override
   public String getMessage() {
         return this.message;
   }
}

In the preceding code snippet, the EmployeeServiceImpl class implemented the EmployeeService interface.

In the beans.xml file, you'll find the following code:

<?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="employeeServiceBean" class="org.packt.Spring.chapter2.beanscope.EmployeeServiceImpl">
   </bean>

</beans>

In the preceding configuration file, we defined employeeServiceBean without any scope, to see the default nature of the bean.

In the PayrollSystem.java class, you'll find the following code:

package org.packt.Spring.chapter2.beanscope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PayrollSystem {

   public static void main(String[] args) {

          ApplicationContext context = new ClassPathXmlApplicationContext(
                     "beans.xml");

         // Retrieve for first time
         EmployeeService employeeServiceA = (EmployeeService) context
                     .getBean("employeeServiceBean");
          employeeServiceA.setMessage("Message by service A");

           System.out
                      .println("employeeServiceA: " + employeeServiceA.getMessage());

          // Retrieve it again
          EmployeeService employeeServiceB = (EmployeeService) context
                      .getBean("employeeServiceBean");
         System.out
                       .println("employeeServiceB: " + employeeServiceB.getMessage());
   }
}

In the preceding code snippet, the PayrollSystem class has the main() method. For the first time, we call getBean("employeeServiceBean"), assign the bean to the employeeServiceA variable of the EmployeeService type, and then set the message by calling the setMessage() method. Again, we call getBean("employeeServiceBean") and assign the bean to the employeeServiceB variable of the EmployeeService type. The output after calling the getMessage() method from both reference variable results is the same, as shown here:

org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1202d69: startup date [Sat Jan 24 20:04:30 IST 2015]; root of context hierarchy
Jan 24, 2015 8:04:30 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
employeeServiceA: Message by service A
employeeServiceB: Message by service A

Singleton

By default, all Spring beans are singleton. Once ApplicationContext is initialized, it looks at all the beans in XML and initializes only one bean per bean definition in Spring Container. On each call to the getBean() method, Spring Container returns the same instance of the bean.

The first bean scope in Spring that is called is singleton, which initializes only one bean per bean definition in the container and returns the same instance reference on each call to the getBean() method. This scope makes Spring initialize all beans during the load time itself without waiting for the getBean() call.

In the beans.xml file, you'll find the following code:

...
<bean id="employeeServiceBean" class="org.packt.Spring.chapter2.beanscope.EmployeeServiceImpl"
         scope="singleton">
</bean>
...

In the preceding configuration file, we have a bean with a singleton scope. When we run PayrollSystem.java, the output will be as follows:

org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1855562: startup date [Sat Jan 24 20:36:27 IST 2015]; root of context hierarchy
Jan 24, 2015 8:36:28 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
employeeServiceA: Message by service A
employeeServiceB: Message by service A

Since the EmployeeServiceImpl bean is in the singleton scope, the second retrieval by employeeServiceB will display the message set by employeeServiceA even though it's retrieved by calling a new getBean() method.

The singleton pattern in general says that overall there will be only one instance of the object. But when we talk about singleton in the Spring Framework, we are talking about Spring Container alone.

We can have multiple containers running in the same JVM, so we can have multiple instances of the same bean in same JVM.

So, singleton in Spring represents in a particular Spring container, and there is only one instance of a bean created in that container that is used across different references.

Prototype

The prototype is second bean scope in Spring, which returns a brand-new instance of a bean on each call to the getBean() method. When a bean is defined as a prototype, Spring waits for getBean() to happen and only then does it initialize the prototype. For every getBean() call, Spring has to perform initialization, so instead of doing default initialization while a context is being created, it waits for a getBean() call. So, every time getBean() gets called, it creates a new instance.

In the beans.xml file, you'll find the following code:

...
   <bean id="employeeServiceBean" class="org.packt.Spring.chapter2.beanscope.EmployeeServiceImpl"
         scope="prototype">
   </bean>
...

In the preceding configuration file, we have a bean with scope as a prototype. When we run the PayrollSystem.java file, the output will be as follows:

org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1855562: startup date [Sat Jan 24 21:05:14 IST 2015]; root of context hierarchy
Jan 24, 2015 9:05:15 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
employeeServiceA: Message by service A
employeeServiceB: null

The configured destruction life cycle callbacks are not called in the case of a prototype. Spring doesn't maintain the complete life cycle of the prototype. Here, the container instantiates and configures prototype beans and returns this bean to the client with no further record of this prototype instance.

Since every getBean() call creates a new instance of the prototype bean, this could lead to performance issues when beans use limited resources such as network connections, whereas it may be useful if you would like to get a new instance of a domain object, such as an employee object.

Request

The third bean scope in Spring is request, which is available only in web applications that use Spring and create an instance of bean for every HTTP request. Here, a new bean is created per Servlet request. Spring will be aware of when a new request is happening because it ties well with the Servlet APIs, and depending on the request, Spring creates a new bean. So, if the request scope has getBean() inside it, for every new request, there will be a new bean. However, as long as it's in the same request scope, the same bean is going to be used.

Session

The session is the fourth bean scope in Spring, which is available only in web applications that use Spring and create an instance of bean for every HTTP session. Here, a new bean is created per session. As long as there is one user accessing in a single session, each call to getBean() will return same instance of the bean. But if it's a new user in a different session, then a new bean instance is created.

Global session

The global session is the fifth bean scope in Spring, which works only in portlet environments that use Spring and create a bean for every new portlet session.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.42.87