Java Spring Scopes Explained

Java Spring framework has several different bean scopes. Today I’ll explain the meaning of each Spring beanscope.

The scope of a bean defines the life cycle and visibility of that bean in the contexts in which it is used.

Java Spring defines 5 different types of scopes:

  • Singleton
  • Prototype
  • Request
  • Session
  • GlobalSession

Request, Session and GlobalSession scopes are only for a web-application.

Singleton Scope

Defining a bean with Singleton scope means that container creates a single instance of that bean, and all requests for that bean name will return the same cached object. Any modifications to the object will be reflected in all references to the bean. This scope is the default scope in Java Spring.

I’ll create a simple Employee class to show Spring scopes concept:

public class Employee {
    private String name;
    private String position;
 
    // ...
}

Now, let’s define the bean with Singleton scope by using Spring @Scope annotation:

@Bean
@Scope("singleton")
public Employee employeeSingleton() {
    return new Employee();
}

Now let’s test our code to ensure that two objects referring to the same bean with the same values:

private static final String NAME = "Bob Norton";
private static final String POSITION= "Software Engineer";

@Test
public void singletonScopeTest() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml");
 
    Employee employeeOne = (Employee) applicationContext.getBean("employeeSingleton");
    Employee employeeTwo = (Employee) applicationContext.getBean("employeeSingleton");
 
    employeeOne.setName(NAME);
    Assert.assertEquals(NAME, employeeTwo.getName());
    
    employeeOne.setName(POSITION);
    Assert.assertEquals(POSITION, employeeTwo.getName());
 
    ((AbstractApplicationContext) applicationContext).close();
}

The scopes.xml contains the xml definitions of the beans:

<?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="employeeSingleton" class="com.codeflex.scopes.Employee" scope="singleton"/>    
</beans>

 

Prototype Scope

A bean with Prototype scope will return a different instance every time it is requested from the container:

@Bean
@Scope("prototype")
public Employee employeePrototype() {
    return new Employee();
}
private static final String BOB = "Bob Norton";
private static final String JOE = "Joe Newton";
 
@Test
public void prototypeScopeTest() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml");
 
    Person employeeOne = (Person) applicationContext.getBean("employeePrototype");
    Person employeeTwo = (Person) applicationContext.getBean("employeePrototype");
 
    employeeOne.setName(BOB);
    employeeTwo.setName(JOE);
 
    Assert.assertEquals(BOB, employeeOne.getName());
    Assert.assertEquals(JOE, employeeTwo.getName());
 
    ((AbstractApplicationContext) applicationContext).close();
}

Don’t forget to edit scopes.xml file and change definition for the bean with prototype scope instead of singleton:

 
<bean id="employeeSingleton" class="com.codeflex.scopes.Employee" scope="prototype"/></beans>

 

Web Application Scopes

Request scope – creates a bean instance for each HTTP request.
Session scope – creates an instance for an HTTP Session
GlobalSession scope – creates an instance for a global HTTP Session.

This is our sample class:

public class Messenger{
 
    private String message;
     
    // ...
}

 

Request Scope

Defining the bean with Request scope:

@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Messenger requestMessage() {
    return new Messenger();
}

The proxyMode attribute is necessary because at the moment of the instantiation of the web application context, there is no active request. Spring will create a proxy to be injected as a dependency, and instantiate the target bean when it is needed in a request.

Now, let’s define a controller that has an injected reference to the Messenger. We need to access the same request twice in order to test the web specific scopes. If we display the message each time the request is running, we can see that the value for the Messenger will go back to the value null, even though it is later changed in the method, because we have a different bean instance for each request.

@Controller
public class SpringScopesController {
    @Resource(name = "requestMessage")
    Messenger requestMessage;
 
    @RequestMapping("/scopes")
    public String getScopes(Model model) {
        requestMessage.setMessage("Java Spring Scopes Explained!");
        model.addAttribute("requestMessage", requestMessage.getMessage());
        return "scopesExample";
    }
}

 

Session Scope

Let’s define a bean with Session scope in a similar manner:

@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Messenger requestMessage() {
    return new Messenger();
}

Next I define a controller with a reference to the sessionMessage bean.

Same, we need to run two requests in order to show that the value of the message field is the same for the session. If we call the request that sets the message for the bean reference once, and then make the same call again and display the message, we will see the value previously set, because there is only one instance of a bean per session:

@Controller
public class SpringScopesController {
    @Resource(name = "sessionMessage") 
    Messenger sessionMessage; 
     
    @RequestMapping("/scopes")
    public String getScopes(Model model) {
        sessionMessage.setMessage("Java Spring Scopes Explained!");
        model.addAttribute("sessionMessage", sessionMessage.getMessage());
        return "scopesExample";
    }
}

 

GlobalSession Scope

@Bean
@Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Messenger requestMessage() {
    return new Messenger();
}

This type of scope is used in applications with a portlet container, each portlet has its own session. The beans with GlobalSession scope will be available over all sessions.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.