Spring – Bean Scopes | Code Factory


Donate : Link

Medium Blog : Link

Applications : Link

This image has an empty alt attribute; its file name is image-1.png

Spring Tutorial Index Page: Link

  • The latest version of Spring framework defines 6 types of scopes:
  1. singleton
  2. prototype
  3. request
  4. session
  5. application
  6. websocket
  • The last four scopes mentioned request, session, application and websocket are only available in a web-aware application.

Take HelloWorld Example from Spring – Hello World Example for practice.

Singleton Scope

  • Defining a bean with singleton scope means the container creates a single instance of that bean, and all requests for that bean name will return the same object, which is cached. Any modifications to the object will be reflected in all references to the bean. This scope is the default value if no other scope is specified.
  • We can declare scope attribute with singleton value or w/o using scope attribute (because default is singleton).
<bean id="t" class="com.codeFactory.beans.Test" />
  • Let’s create a Employee entity to exemplify the concept of scopes
public class Employee {
    private String name;

    // standard constructor, getters and setters
}
  • We can define the bean with singleton scope by using the @Scope annotation
@Bean
@Scope("singleton")
public Employee employeeSingleton() {
    return new Employee();
}
  • We can also use a constant instead of the String value in the following manner
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
  • Now create two objects using .getbean("id") and compare both and you can see that both referencing the same bean instance.

Prototype Scope

  • A bean with prototype scope will return a different instance every time it is requested from the container. It is defined by setting the value prototype to the @Scope annotation in the bean definition
@Bean
@Scope("prototype")
public Employee employeePrototype() {
    return new Employee();
}
  • The spring.xml file is similar to the xml definition for the bean with prototype scope
<bean id="t" class="com.codeFactory.beans.Test" scope="prototype" />
  • We could also use a constant as we did for the singleton scope
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  • Now create two objects using .getbean("id") and compare both and you can see that both referencing the same different bean instance.

Web Aware Scopes

  • As mentioned, there are four additional scopes that are only available in a web-aware application context. These are less often used in practice.
  • * The request scope creates a bean instance for a single HTTP request while session scope creates for an HTTP Session.
  • * The application scope creates the bean instance for the lifecycle of a ServletContext and the websocket scope creates it for a particular WebSocket session.
  • Let’s create a class to use for instantiating the beans
public class HelloMessageGenerator {
    private String message;
    
    // standard getter and setter
}

Request Scope

  • We can define the bean with request scope using the @Scope annotation.
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
    return new HelloMessageGenerator();
}
  • 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.
  • We can also use a @RequestScope composed annotation that acts as a shortcut for the above definition.
@Bean
@RequestScope
public HelloMessageGenerator requestScopedBean() {
    return new HelloMessageGenerator();
}
  • Next, we can define a controller that has an injected reference to the requestScopedBean. 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 run, we can see that the value is reset to null, even though it is later changed in the method. This is because of a different bean instance being returned for each request.
@Controller
public class ScopesController {
    @Resource(name = "requestScopedBean")
    HelloMessageGenerator requestScopedBean;

    @RequestMapping("/scopes/request")
    public String getRequestScopeMessage(final Model model) {
        model.addAttribute("previousMessage", requestScopedBean.getMessage());
        requestScopedBean.setMessage("Good morning!");
        model.addAttribute("currentMessage", requestScopedBean.getMessage());
        return "scopesExample";
    }
}

Session Scope

  • We can define the bean with session scope in a similar manner.
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator sessionScopedBean() {
    return new HelloMessageGenerator();
}
  • There’s also a dedicated composed annotation we can use to simplify the bean definition.
@Bean
@SessionScope
public HelloMessageGenerator sessionScopedBean() {
    return new HelloMessageGenerator();
}
  • Next, we define a controller with a reference to the sessionScopedBean. Again, we need to run two requests in order to show that the value of the message field is the same for the session.
  • In this case, when the request is made for the first time, the value message is null. But once, it is changed, then that value is retained for subsequent requests as the same instance of the bean is returned for the entire session.
@Controller
public class ScopesController {
    @Resource(name = "sessionScopedBean")
    HelloMessageGenerator sessionScopedBean;

    @RequestMapping("/scopes/session")
    public String getSessionScopeMessage(final Model model) {
        model.addAttribute("previousMessage", sessionScopedBean.getMessage());
        sessionScopedBean.setMessage("Good afternoon!");
        model.addAttribute("currentMessage", sessionScopedBean.getMessage());
        return "scopesExample";
    }
}

Application Scope

  • The application scope creates the bean instance for the lifecycle of a ServletContext.
  • This is similar to the singleton scope but there is a very important difference with regards to the scope of the bean.
  • When beans are application scoped the same instance of the bean is shared across multiple servlet-based applications running in the same ServletContext, while singleton-scoped beans are scoped to a single application context only.
  • Let’s create the bean with application scope.
@Bean
@Scope(
  value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator applicationScopedBean() {
    return new HelloMessageGenerator();
}
  • Analogously as for the request and session scopes, we can use a shorter version.
@Bean
@ApplicationScope
public HelloMessageGenerator applicationScopedBean() {
    return new HelloMessageGenerator();
}
  • Now, let’s create a controller that references this bean.
@Controller
public class ScopesController {
    @Resource(name = "applicationScopedBean")
    HelloMessageGenerator applicationScopedBean;

    @RequestMapping("/scopes/application")
    public String getApplicationScopeMessage(final Model model) {
        model.addAttribute("previousMessage", applicationScopedBean.getMessage());
        applicationScopedBean.setMessage("Good afternoon!");
        model.addAttribute("currentMessage", applicationScopedBean.getMessage());
        return "scopesExample";
    }
}
  • In this case, value message once set in the applicationScopedBean will be retained for all subsequent requests, sessions and even for a different servlet application that will access this bean, provided it is running in the same ServletContext.

WebSocket Scope

  • Finally, let’s create the bean with websocket scope.
@Bean
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator websocketScopedBean() {
    return new HelloMessageGenerator();
}
  • WebSocket-scoped beans when first accessed are stored in the WebSocket session attributes. The same instance of the bean is then returned whenever that bean is accessed during the entire WebSocket session.
  • We can also say that it exhibits singleton behavior but limited to a WebSocket session only.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s