Understanding Spring Bean Scopes
In Spring framework, beans are the core building blocks used to develop an application. Bean scopes define the lifecycle and visibility of the beans in different contexts of the application.
Table of Contents
Understanding bean scopes is crucial to ensure that the beans behave as expected and optimize application performance.
Spring framework provides six different types of bean scopes.
- singleton
- prototype
- request
- session
- application
- websocket
request, session, application, and websocket are exclusively designed for web applications. It is essential to note that the scope of a bean is a crucial aspect to consider when creating a bean, as it directly affects the behavior and functionality of the application.
1. Singleton Scope
Singleton scope is the default scope for all Spring Beans. The Singleton scope creates only one instance of a bean for the entire lifecycle of the application context. Anytime a bean with the Singleton scope is requested, the same instance of the bean is returned.
Here is an example of defining a bean with Singleton scope in Spring Boot:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MySingletonBean mySingletonBean() {
return new MySingletonBean();
}
}
In the above example, the MySingletonBean class is defined as a Spring Bean with the @Bean annotation. Since no scope is specified, it will default to the Singleton scope. This means that the mySingletonBean() method will only be called once during the application context's lifecycle, and every time mySingletonBean() is called, the same instance of MySingletonBean will be returned.
Here is an example of using the MySingletonBean in another class:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private MySingletonBean singletonBean;
@Autowired
public MyService(MySingletonBean singletonBean) {
this.singletonBean = singletonBean;
}
//...
}
In the above example, the MyService class is a Spring Bean that uses MySingletonBean. The MySingletonBean is autowired in the constructor of the MyService class. Since MySingletonBean has a Singleton scope, the same instance of the MySingletonBean is injected every time MyService is created.
2. Prototype Scope
Prototype scope creates a new instance of a bean every time it is requested. The Prototype scope is useful when you want to create and configure multiple instances of the same bean with different values or states.
Here is an example of defining a bean with Prototype scope.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public MyPrototypeBean myPrototypeBean() {
return new MyPrototypeBean();
}
}
In the above example, the MyPrototypeBean class is defined as a Spring Bean with the @Bean annotation. The @Scope("prototype") annotation is used to specify the Prototype scope for this bean. This means that every time the myPrototypeBean() method is called, a new instance of MyPrototypeBean will be returned.
Here is an example of using the MyPrototypeBean in another class:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private MyPrototypeBean prototypeBean;
@Autowired
public MyService(MyPrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public void doSomething() {
// use the prototype bean
}
}
In the above example, the MyService class is a Spring Bean that uses MyPrototypeBean. The MyPrototypeBean is autowired in the constructor of the MyService class. Since MyPrototypeBean has a Prototype scope, every time doSomething() is called, a new instance of MyPrototypeBean is created and used. This can be useful if you want to create and use multiple instances of MyPrototypeBean with different values or states.
3. Request Scope
In Spring, the Request scope is designed exclusively for web-aware applications. The Request scope creates a new instance of a bean for each HTTP request. This means that every time an HTTP request is made, a new instance of a Request scoped bean is created and associated with that request. Once the request is completed, the bean instance is destroyed.
Here is an example of defining a bean with a Request scope in Spring:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.RequestScope;
@Configuration
public class AppConfig {
@Bean
@RequestScope
public MyRequestScopedBean myRequestScopedBean() {
return new MyRequestScopedBean();
}
}
@RequestScope is a shortcut for @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
In the above example, the MyRequestScopedBean class is defined as a Spring Bean with the @Bean annotation. The @RequestScope annotation is used to specify the Request scope for this bean. This means that every time an HTTP request is made, a new instance MyRequestScopedBean will be created and associated with that request.
Here is an example of using the MyRequestScopedBean in a web controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
private MyRequestScopedBean requestScopedBean;
@Autowired
public MyController(MyRequestScopedBean requestScopedBean) {
this.requestScopedBean = requestScopedBean;
}
@GetMapping("/my-page")
public String myPage(Model model) {
// use the request scoped bean
model.addAttribute("message", requestScopedBean.getMessage());
return "my-page";
}
}
In the above example, the MyController is a Spring MVC controller that uses MyRequestScopedBean. The MyRequestScopedBean is autowired in the constructor of the MyController class. Since MyRequestScopedBean has a Request scope, every time an HTTP request is made to the /my-page endpoint, a new instance of MyRequestScopedBean is created and associated with that request. The message from the MyRequestScopedBean is added to the Model and used in the view returned by the controller. Once the request is completed, the instance of MyRequestScopedBean is destroyed.
4. Session Scope
In Spring, the Session scope is designed exclusively for web-aware applications. The Session scope creates a new instance of a bean for each user session. This means that every time a user starts a new session, a new instance of a Session scoped bean is created and associated with that session. Once the session ends, the bean instance is destroyed.
Here is an example of defining a bean with Session scope in Spring:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.SessionScope;
@Configuration
public class AppConfig {
@Bean
@SessionScope
public MySessionScopedBean mySessionScopedBean() {
return new MySessionScopedBean();
}
}
@SessionScope is a shortcut form of @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
In the above example, the MySessionScopedBean class is defined as a Spring Bean with the @Bean annotation. The @SessionScope annotation is used to specify the Session scope for this bean. This means that every time a user starts a new session, a new instance of MySessionScopedBean will be created and associated with that session.
Here is an example of using the MySessionScopedBean in a web controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
private MySessionScopedBean sessionScopedBean;
@Autowired
public MyController(MySessionScopedBean sessionScopedBean) {
this.sessionScopedBean = sessionScopedBean;
}
@GetMapping("/my-page")
public String myPage(Model model) {
// use the session scoped bean
model.addAttribute("message", sessionScopedBean.getMessage());
return "my-page";
}
}
In the above example, the MyController is a Spring MVC controller that uses MySessionScopedBean. The MySessionScopedBean is autowired in the constructor of the MyController class. Since MySessionScopedBean has a Session scope, every time a user starts a new session and makes a request to the /my-page endpoint, a new instance of MySessionScopedBean is created and associated with that session. The message from the MySessionScopedBean is added to the Model and used in the view returned by the controller. Once the session ends, the instance of MySessionScopedBean is destroyed.
5. Application Scope
Application scope creates a single instance of a bean for the entire lifetime of the application. This means that a single instance of an Application scoped bean is created when the application starts up, and this same instance is used throughout the entire lifetime of the application.
Here is an example of defining a bean with Application scope in Spring:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.ApplicationScope;
@Configuration
public class AppConfig {
@Bean
@ApplicationScope
public MyApplicationScopedBean myApplicationScopedBean() {
return new MyApplicationScopedBean();
}
}
In the above example, the MyApplicationScopedBean class is defined as a Spring Bean with the @Bean annotation. The @ApplicationScope annotation is used to specify the Application scope for this bean. This means that a single instance of MyApplicationScopedBean will be created when the application starts up, and this same instance will be used throughout the entire lifetime of the application.
Here is an example of using the MyApplicationScopedBean in a web controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
private MyApplicationScopedBean applicationScopedBean;
@Autowired
public MyController(MyApplicationScopedBean applicationScopedBean) {
this.applicationScopedBean = applicationScopedBean;
}
@GetMapping("/my-page")
public String myPage(Model model) {
// use the application scoped bean
model.addAttribute("message", applicationScopedBean.getMessage());
return "my-page";
}
}
In the above example, the MyController is a Spring MVC controller that uses MyApplicationScopedBean. The MyApplicationScopedBean is autowired in the constructor of the MyController class. Since MyApplicationScopedBean has an Application scope, a single instance of MyApplicationScopedBean is created when the application starts up, and this same instance is used throughout the entire lifetime of the application. The message from the MyApplicationScopedBean is added to the Model and used in the view returned by the controller.
6. WebSocket Scope
WebSocket scope in Spring is a relatively new scope that was introduced in version 4.2. It is designed to create a single instance of a bean for the duration of a WebSocket session. A WebSocket session is created when a client establishes a connection to a server over the WebSocket protocol.
Here is an example of defining a bean with WebSocket scope in Spring:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.WebSocketScope;
@Configuration
public class AppConfig {
@Bean
@WebSocketScope
public MyWebSocketScopedBean myWebSocketScopedBean() {
return new MyWebSocketScopedBean();
}
}
In the above example, the MyWebSocketScopedBean class is defined as a Spring Bean with the @Bean annotation. The @WebSocketScope annotation is used to specify the WebSocket scope for this bean. This means that a single instance of MyWebSocketScopedBean will be created for the duration of a WebSocket session.
Here is an example of using the MyWebSocketScopedBean in a WebSocket handler:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
@Component
public class MyWebSocketHandler extends AbstractWebSocketHandler {
private MyWebSocketScopedBean webSocketScopedBean;
@Autowired
public MyWebSocketHandler(MyWebSocketScopedBean webSocketScopedBean) {
this.webSocketScopedBean = webSocketScopedBean;
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
// use the WebSocket scoped bean
String response = webSocketScopedBean.getResponse(message.getPayload());
session.sendMessage(new TextMessage(response));
}
}
In the above example, the MyWebSocketHandler is a Spring component that uses MyWebSocketScopedBean. The MyWebSocketScopedBean is autowired in the constructor of the MyWebSocketHandler class. Since MyWebSocketScopedBean has a WebSocket scope, a single instance of MyWebSocketScopedBean is created for the duration of a WebSocket session. The handleTextMessage method is called each time a client sends a message over the WebSocket connection. The message payload is used to get a response from the MyWebSocketScopedBean, and this response is sent back to the client.