Spring Bean Scopes: Guide to understand the different Bean scopes

Introduction

This tutorial shows the different scopes you can assign to a Bean or a Component in Spring Framework.

It’s important to understand that a Bean definition is just a recipe to create instances of a class following the definition of this recipe. This recipe can be then used one or more times during the life cycle of the application to create an instance of the Bean.

The Bean scope is one of the main characteristics of the Bean configuration in Spring. The scope will indicate when and how is the object for the Bean definition going to be instantiated.

Spring includes 7 different Bean scopes:

Singleton

Prototype

Request

Session

Global session

Application

Websocket

From these, only 5 of them are available in a web-aware application.

Singleton

Singleton is the default scope for a Bean, the one that will be used if nothing else is indicated. This scope implies that Spring container will create an only shared instance of the class designated by this bean, so each time the Bean is required the same object will be injected. The instance of this Bean is stored in a cache managed by Spring.

We can use annotations to define singletons as in the following example:

Definición de Beans con ámbito Singleton

Java

1

2

3

4

5

6

7

8

9

10

@Bean(name=SINGLETON_BEAN_SAMPLE_NAME)

publicSample sample(){

returnnewSample();

}

@Bean(name=SINGLETON_ANNOTATED_BEAN_SAMPLE_NAME)

@Scope(SCOPE_SINGLETON)

publicSample sampleAnnotated(){

returnnewSample();

}

As already stated, Singleton is the default scope for a Spring Bean, so it’s not necessary to define its @Scope (first example). However, for better clarity and understanding, you can highlight this fact by using the @Scope annotation as in the second example.

Prototype

In the Prototype scope, Spring container will create a new instance of the object described by the bean each time it receives a request. One of the basic rules stated in Spring’s documentation is to use Prototype scoped beans when working on an environment where there is session management (Stateful) and use Singleton scope when working on environments without session management (Stateless), however there are many other more and different use cases.

It’s important to highlight that the Spring container doesn’t take responsibility for what happens to the instances of the objects received when requesting a bean. This means that it’s the developer’s task to perform clean up and free the resources referenced by the object defined by the Bean.

Same as with Singleton scope, we can define a bean with Prototype scope using annotations as follows::

Singleton Beans with injected Prototype Beans

It’s very important to highlight that when you define a Singleton Bean with dependencies or encapsulated Prototype Beans, injection happens when the Singleton object is instantiated so injection just happens once. Thus the injected object defined by the Prototype Bean will always be the same instance even though it was defined with a Prototype scope.

For example, we can define a class with an injected Bean as follows:

Clase con Bean inyectado

1

2

3

4

5

6

7

8

publicclassSampleAutowired{

@Autowired

@Qualifier(BEAN_NAME_FOR_AUTOWIRED_PROTOTYPE)

privateSample sampleAutowiredPrototype;

/* ... */

}

We define the following Beans:

Definición de beans para inyección

1

2

3

4

5

6

7

8

9

10

11

12

@Bean(name=PROTOTYPE_BEAN_SAMPLE_NAME)

@Scope(SCOPE_PROTOTYPE)

@Qualifier(BEAN_NAME_FOR_AUTOWIRED_PROTOTYPE)

publicSample samplePrototype(){

returnnewSample();

}

@Bean(name=SINGLETON_BEAN_SAMPLE_AUTOWIRED_NAME)

@Scope(SCOPE_SINGLETON)

publicSampleAutowired sampleAutowiredPrototype(){

returnnewSampleAutowired();

}

The first Bean (Sample) has a Prototype scope and will be injected in the second (SampleAutowired) which has a Singleton scope. As explained in the previous paragraphs, the expected behavior is that each time we request a SampleAutowired, the instance of Sample will be the same even when it has a Prototype scope because it was instantiated and assigned only once when SampleAutowired (Singleton) was first instantiated..

Session

Spring container will create a new instance of the object defined by the Bean for each of the HTTP sessions (Stateful application) and will return this same instance each time it receives a request within the same session.

Bean de ámbito Sesión

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// Beans based on @Bean annotations

@Bean

@Scope(value=WebApplicationContext.SCOPE_SESSION)

publicBeanSample beanSample(){

returnnewBeanSample();

}

//Beans based on @Component annotations

@RestController

@SessionScope

publicclassSessionScopedControllerextendsAbstractController{

@GetMapping(AbstractController.SESSION_SCOPE_ENDPOINT)

publicStringgetUuid(){

returnsuper.getUuid();

}

}

The behavior for the @RestController in the previous snippet can be tested as follows:

Global Session

The Global Session scope has a behavior similar to the Session scope but it’s only applicable in the context of Portlet based web applications. The Portlet specification defines a global session as a session that’s shared amongst al the Portlets that make up an application.

If this scope is used in a regular web application, the behavior of the Beans defined with this scope will be the same as if they had been defined with a Session scope.

Bean de ámbito Global Sesión

Java

1

2

3

4

5

@Bean

@Scope(value=WebApplicationContext.SCOPE_GLOBAL_SESSION)

publicBeanSample beanSample(){

returnnewBeanSample();

}

Application

The Application scope has a behavior very similar to the Singleton scope, Spring will create a new instance fo the bean for each ServletContext. A Spring application can have several ServletContext, so the instance returned by Spring for each Bean request will be the same within the same context, but different for each of the contexts.

Websocket

The Spring container will create a new instance of the object defined by the Bean and return this instance for each request produced within the lifecycle of a Websocket.

Conclusion

This post can be used as a quick guide to understand the different scopes availabe in a Spring application. There are practical examples and unit tests to prove each of the behaviors. The full source code for this post can be found at Github.