A logo showing the text blog.marcnuri.com
Español
Home»Java»Spring Bean Scopes: Guide to understand the different Bean scopes

Recent Posts

  • Fabric8 Kubernetes Client 7.2 is now available!
  • Connecting to an MCP Server from JavaScript using AI SDK
  • Connecting to an MCP Server from JavaScript using LangChain.js
  • The Future of Developer Tools: Adapting to Machine-Based Developers
  • Connecting to a Model Context Protocol (MCP) Server from Java using LangChain4j

Categories

  • Artificial Intelligence
  • Front-end
  • Go
  • Industry and business
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • February 2020
  • January 2020
  • December 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • July 2017
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Spring Bean Scopes: Guide to understand the different Bean scopes

2018-04-30 in Java tagged Bean / Java / Scopes / Spring Framework / Spring Boot / Testing by Marc Nuri | Last updated: 2021-03-27
Versión en Español

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:

1@Bean(name = SINGLETON_BEAN_SAMPLE_NAME)
2public Sample sample() {
3  return new Sample();
4}
5
6@Bean(name = SINGLETON_ANNOTATED_BEAN_SAMPLE_NAME)
7@Scope(SCOPE_SINGLETON)
8public Sample sampleAnnotated() {
9  return new Sample();
10}

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.

The following test shows the behavior of a singleton:

1@Test
2public void singletonTest_na_shouldBeSameInstance() {
3  Sample singleton1 = applicationContext.getBean(SINGLETON_BEAN_SAMPLE_NAME, Sample.class);
4  Sample singleton2 = applicationContext.getBean(SINGLETON_BEAN_SAMPLE_NAME, Sample.class);
5  Assert.assertEquals(singleton1, singleton2);
6  Sample singletonAnnotated1 = applicationContext.getBean(SINGLETON_ANNOTATED_BEAN_SAMPLE_NAME, Sample.class);
7  Sample singletonAnnotated2 = applicationContext.getBean(SINGLETON_ANNOTATED_BEAN_SAMPLE_NAME, Sample.class);
8  Assert.assertEquals(singletonAnnotated1, singletonAnnotated2);
9  Assert.assertNotEquals(singleton1, singletonAnnotated1);
10}

The behavior for @Component (or any of its extensions) annotated classes is the same as for regular Beans, they will be singleton unless configured differently.

For example, a @RestController as the following:

1@RestController
2public class SingletonScopedController extends AbstractController {
3  /* ... */
4  @GetMapping(AbstractController.SINGLETON_SCOPE_ENDPOINT)
5  public String getUuid() {
6    return super.getUuid();
7  }
8}

Will assert the following test:

1@Test
2public void singletonScopedController_na_shouldReturnSameValues() throws Exception {
3  String response1 = mockMvc.perform(get(AbstractController.SINGLETON_SCOPE_ENDPOINT))
4      .andReturn().getResponse().getContentAsString();
5  String response2 = mockMvc.perform(get(AbstractController.SINGLETON_SCOPE_ENDPOINT))
6      .andReturn().getResponse().getContentAsString();
7  Assert.assertEquals(response1, response2);
8}

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::

1@Bean(name = PROTOTYPE_BEAN_SAMPLE_NAME)
2@Scope(SCOPE_PROTOTYPE)
3public Sample samplePrototype() {
4  return new Sample();
5}

The next test shows the behavior of a prototype:

1@Test
2public void prototypeTest_na_shouldBeDifferentInstance() {
3  Sample prototype1 = applicationContext.getBean(PROTOTYPE_BEAN_SAMPLE_NAME, Sample.class);
4  Sample prototype2 = applicationContext.getBean(PROTOTYPE_BEAN_SAMPLE_NAME, Sample.class);
5  Assert.assertNotEquals(prototype1, prototype2);
6}

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:

1public class SampleAutowired {
2
3  @Autowired
4  @Qualifier(BEAN_NAME_FOR_AUTOWIRED_PROTOTYPE)
5  private Sample sampleAutowiredPrototype;
6
7  /* ... */
8}

We define the following Beans:

1@Bean(name = PROTOTYPE_BEAN_SAMPLE_NAME)
2@Scope(SCOPE_PROTOTYPE)
3@Qualifier(BEAN_NAME_FOR_AUTOWIRED_PROTOTYPE)
4public Sample samplePrototype() {
5  return new Sample();
6}
7
8@Bean(name = SINGLETON_BEAN_SAMPLE_AUTOWIRED_NAME)
9@Scope(SCOPE_SINGLETON)
10public SampleAutowired sampleAutowiredPrototype() {
11  return new SampleAutowired();
12}

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..

This is proved in the following test:

1@Test
2public void singletonWithAutowiredPrototype_na_shouldBeInstance() {
3  SampleAutowired singleton1 = applicationContext.getBean(SINGLETON_BEAN_SAMPLE_AUTOWIRED_NAME, SampleAutowired.class);
4  SampleAutowired singleton2 = applicationContext.getBean(SINGLETON_BEAN_SAMPLE_AUTOWIRED_NAME, SampleAutowired.class);
5  Assert.assertEquals(singleton1, singleton2);
6  Assert.assertEquals(singleton1.getSampleAutowiredPrototype(), singleton2.getSampleAutowiredPrototype());
7}

Web-aware application scopes

As mentioned in the introduction, the rest of the scopes are only available for web-aware applications.

Request

The Spring container will create a new instance of the object defined by the Bean each time it receives an HTTP request.

To define a Bean with this scope we can use the following annotations depending on if it’s a Bean or a Component:

1// Beans based on @Bean annotations
2@Bean
3@Scope(value = WebApplicationContext.SCOPE_REQUEST)
4public BeanSample beanSample() {
5    return new BeanSample ();
6}
7
8// Beans based on @Component annotations
9@RestController()
10@RequestScope
11public class RequestScopedController extends AbstractController{
12
13  @GetMapping(AbstractController.REQUEST_SCOPE_ENDPOINT)
14  public String getUuid() {
15    return super.getUuid();
16  }
17
18}

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

1@Test
2public void requestScopedController_na_shouldReturnDifferentValues() throws Exception {
3  String response1 = mockMvc.perform(get(AbstractController.REQUEST_SCOPE_ENDPOINT))
4      .andReturn().getResponse().getContentAsString();
5  String response2 = mockMvc.perform(get(AbstractController.REQUEST_SCOPE_ENDPOINT))
6      .andReturn().getResponse().getContentAsString();
7  Assert.assertNotEquals(response1, response2);
8}

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.

1// Beans based on @Bean annotations
2@Bean
3@Scope(value = WebApplicationContext.SCOPE_SESSION)
4public BeanSample beanSample() {
5    return new BeanSample ();
6}
7
8//Beans based on @Component annotations
9@RestController
10@SessionScope
11public class SessionScopedController extends AbstractController {
12
13  @GetMapping(AbstractController.SESSION_SCOPE_ENDPOINT)
14  public String getUuid() {
15    return super.getUuid();
16  }
17}

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

1@Test
2public void sessionScopedController_na_shouldReturnSameValues() throws Exception {
3  MockHttpSession session1 = new MockHttpSession();
4  MockHttpSession session2 = new MockHttpSession();
5  String response1_1 = mockMvc.perform(get(AbstractController.SESSION_SCOPE_ENDPOINT).session(session1))
6      .andReturn().getResponse().getContentAsString();
7  String response1_2 = mockMvc.perform(get(AbstractController.SESSION_SCOPE_ENDPOINT).session(session1))
8      .andReturn().getResponse().getContentAsString();
9  Assert.assertEquals(response1_1, response1_2);
10  String response2_1 = mockMvc.perform(get(AbstractController.SESSION_SCOPE_ENDPOINT).session(session2))
11      .andReturn().getResponse().getContentAsString();
12  String response2_2 = mockMvc.perform(get(AbstractController.SESSION_SCOPE_ENDPOINT).session(session2))
13      .andReturn().getResponse().getContentAsString();
14  Assert.assertEquals(response2_1, response2_2);
15  Assert.assertNotEquals(response1_1, response2_1);
16}

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.

1@Bean
2@Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION)
3public BeanSample beanSample() {
4    return new BeanSample ();
5}

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.

References

https://docs.spring.io/spring-framework/docs/4.3.12.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-scopes

Scopes in a Spring Bean application
Scopes in a Spring Bean application

Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Post navigation
Spring Bean Scopes: Singleton with PrototypesJava 10: Testing the new release
© 2007 - 2025 Marc Nuri