In this post, we’ll learn about the scope of Beans in the Spring Framework.
· Singleton Scope
· Prototype Scope
· Web-aware application scopes
∘ Request scope
∘ Session Scope
∘ Application Scope
∘ WebSocket Scope
· Conclusion
· References
The scope of a bean determines its lifecycle and visibility within the container. Beans can be defined to be deployed in one of several scopes. Spring Framework supports several types of bean scopes, each of which controls how and when beans are instantiated and shared across the application.
The latest version of the Spring framework defines 6 types of scopes, four of which are available only if you use a web-aware ApplicationContext.
- singleton
- prototype
- request
- session
- application
- websocket
Singleton Scope
The singleton is the default bean scope in the spring container.
A single instance of the class designated by this bean will be created and shared across the entire spring container.
This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object.
Let’s define a bean with singleton scope using @Scope annotation
@Configuration
public class AppConfig {
@Bean
@Scope(value= ConfigurableBeanFactory.SCOPE_SINGLETON)
public Book aSingletonBean() {
return new Book();
}
}
Now, let’s write a unit test class to verify the beans:
@Autowired
ApplicationContext applicationContext;
@Test
void testSingletonBean() {
Object singleton1 = applicationContext.getBean("aSingletonBean");
System.out.println(singleton1);
Object singleton2 = applicationContext.getBean("aSingletonBean");
System.out.println(singleton2);
assertSame(singleton1, singleton2, "Singleton beans should be the same instance");
assertEquals(singleton1.hashCode(), singleton2.hashCode());
}

Prototype Scope
A bean with the prototype scope will return a different instance every time it is requested from the container. Every time we call getBean(), a new instance is returned.
In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance.
@Component
@Scope(value= ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeBean {
private final Random random = new Random();
private final Integer id = random.nextInt(1000);
public Book getCounter() {
return new Book(id);
}
}
@Test
void testPrototypeBean() {
PrototypeBean prototypeBean1 = (PrototypeBean) applicationContext.getBean("prototypeBean");
System.out.println(prototypeBean1);
System.out.println("prototypeBean1, id = : "+prototypeBean1.getCounter().getId());
System.out.println("-----------------------------------");
PrototypeBean prototypeBean2 = (PrototypeBean) applicationContext.getBean("prototypeBean");
System.out.println(prototypeBean2);
System.out.println("prototypeBean2, id = : "+prototypeBean2.getCounter().getId());
assertNotEquals(prototypeBean1.hashCode(), prototypeBean2.hashCode());
assertNotEquals(prototypeBean1, prototypeBean2);
}
As we explained every time we call the getBean() method, a new instance of Prototype Bean is returned.

Web-aware application scopes
As previously mentioned, four scopes are only available in a web-aware application context. The request, session, application, and websocket Scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope being thrown.
Request scope
The Spring IoC creates a new instance of the object defined by the Bean each time it receives an HTTP request and destroys it at the end of the request.
We can define the bean with the request scope using the @RequestScope annotation.
@Component
@RequestScope
public class RequestBean {
private final Random random = new Random();
private final Integer id = random.nextInt(1000);
public String getRequestInfo() {
return "Request ID: " + id;
}
}
Next, we’ll define a @RestController that uses this request-scoped bean.
@RestController
public class RequestScopedController {
@Autowired
private RequestBean requestBean;
@GetMapping("/request-info")
public String getRequestInfo() {
return requestBean.getRequestInfo();
}
}
Each time a new HTTP request comes in, a new instance of RequestBean will be injected into the controller.
If multiple clients make requests to the /request-info endpoint, each request will have its own RequestID instance. For instance:
- Client 1: Sends a request to
/request-info, and receivesRequest ID: 69 - Client 2: Sends a request to
/request-info, and receivesRequest ID: 234
Session Scope
Spring IoC creates a new instance of the object defined by the Bean for each HTTP session (Stateful application) and returns this same instance each time it receives a request within the same session. The bean is created once per HTTP session and destroyed when the session ends.
Like Request scope, we use @SessionScope annotation.
@Component
@SessionScope
public class SessionBean {
private final Random random = new Random();
private final Integer id = random.nextInt(1000);
public String getSessionInfo() {
return "Session ID: " + id;
}
}
@RestController
public class SessionScopedController {
@Autowired
private SessionBean sessionBean;
@GetMapping("/session-info")
public String getSessionInfo() {
return sessionBean.getSessionInfo();
}
}
Data in a session-scoped bean persists across multiple HTTP requests for the same client (browser for example), which is ideal for scenarios like maintaining user login states, preferences, and other session-specific data.
Application Scope
The application scope creates the bean instance for the lifecycle of a ServletContext. This is similar to the singleton scope, but the bean is scoped at the ServletContext level and stored as a regular ServletContext attribute.
Consider the following bean with the application scope:
@Component
@ApplicationScope
public class ApplicationBean {
private String appVersion = "1.0.0";
public String getAppVersion() {
return appVersion;
}
public void setAppVersion(String appVersion) {
this.appVersion = appVersion;
}
}
The Spring container creates a new instance of the ApplicationBean bean once for the entire web application. The bean is scoped at the ServletContext level and stored as a regular ServletContext attribute. Application Scope beans are created and managed by the Spring container. These beans are typically created during the initialization of Spring ApplicationContext and exist for the lifetime of the context. The beans are also destroyed when the application context is destroyed (typically when the application shuts down).
WebSocket Scope
WebSocket scope is associated with the lifecycle of a WebSocket session and applies to STOMP over WebSocket applications.
@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebsocketBean {
}
Conclusion
In this post, we explored the different Bean scopes available in the Spring framework. The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes.
The complete source code is available on GitHub.
Thank you for reading!! See you in the next post.