Khái quát về Spring Bean Scope
- Giới thiệu
Bean là một khái niệm cực kỳ quan trọng của Spring framework. Vì vậy, hiểu rõ về Spring bean và sử dụng nó một cách hiệu quả là đặc biệt quan trọng.
Tuy nhiên, hiện tại lại không có một định nghĩa thực sự rõ ràng nào về Bean. Có khá nhiều định nghĩa về bean trên internet nhưng tựu trung lại còn khá mơ hồ. Dưới đây là định nghĩa của Spring về Bean, mình xin trích dẫn lại:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
Scope của một bean định nghĩa life cycle và tính visibility của bean đó trong constext. Spring framework mới nhất(5.1.5.RELEASE)định nghĩa 6 types của scopes như sau:
- Singleton
- Prototype
- Request
- Session
- Application
- Websocket
4 scope cuối bao gồm Request, Session, Application, Websocket chỉ dùng cho web applications
2. Singleton Scope
Singleton là scope mặc định của Spring bean, có nghĩa là nếu khi định nghĩa bean mà bạn không chỉ rõ scope cho bean đó thì mặc định nó là Singleton. Với singleton scope thì Spring container sẽ tạo một single instant cho bean đó sau đó lưu vào bộ nhớ cached và tất cả các request tới bean đó sẽ trả về duy nhất instant này. Dưới đây là một ví dụ về tạo bean với scope là singleton bằng cách sử dụng @Scope annotation
public class Student {
private String name;
private int age;
@Bean
@Scope("singleton")
public Student studentSingleton(){
return new Student();
}
}
Chúng ta có thể sử dụng constant thay vì sử dụng String value
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
Chúng ta cũng hoàn toàn có thề định nghĩa singleton bean bằng XML configuration như dưới đây.
<bean id="studentSingleton" class="org.khoa.nguyen.dang.beans.Student" scope="singleton" />
3. Prototype Scope
Một bean được định nghĩa với scope là prototype thì Spring container sẽ trả về instant khác nhau cho mỗi request. Sử dụng annotation @Scope để định nghĩa một bean có scope là protory như sau:
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Student studentPrototype() {
return new Student();
}
Sử dụng XML để định nghĩa 1 bean cũng giống như định nghĩa một singleton bean, chỉ thay value là prototype
<bean id="studentProtorype" class="org.khoa.nguyen.dang.beans.Student" scope="prototype" />
4. Web Application scopes
4.1 Request scope
Một bean được định nghỉa là request scope có nghĩa là Spring container sẽ tạo một instant cho một HTTP request.
Sử dụng @Scope annotation để định nghĩa một bean có scope là request như sau
public class MessageGenerator {
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public MessageGenerator generateHelloMessage(){
return new MessageGenerator();
}
}
Tiếp theo, hãy định nghĩa một Controller và inject bean generateHelloMessage vào
@Controller
public class MessageController {
@Resource(name = "generateHelloMessage")
MessageGenerator generateHelloMessage;
@RequestMapping("/message/morning")
public String goodMorningMessage(final Model model){
//This will return null for every request at every time
model.addAttribute("previousMessage", generateHelloMessage.getMessage());
generateHelloMessage.setMessage("Good morning!");
model.addAttribute("currentMessage", generateHelloMessage.getMessage());
return "Example";
}
}
4.2 Session scope
Một bean được định nghỉa là session scope có nghĩa là Spring container sẽ tạo một instant cho một HTTP session. Sử dụng @Scope để định nghĩa một session bean như sau:
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public MessageGenerator generateSessionMessage(){
return new MessageGenerator();
}
Tiếp theo, Sử dụng lại MessageController và inject bean generateSessionMessage vào
@Controller
public class MessageController {
@Resource(name = "generateSessionMessage")
MessageGenerator generateSessionMessage;
@RequestMapping("/message/session")
public String sessionMessage(final Model model){
//This will return null for the first time. But, after changed the value is retained for every request
model.addAttribute("previousMessage", generateSessionMessage.getMessage());
generateSessionMessage.setMessage("Good morning!");
model.addAttribute("currentMessage", generateSessionMessage.getMessage());
return "Example";
}
}
4.3 Application scope
Application scope sẽ tạo một bean instance cho lifecycle của một ServletContext
Application scope thì cũng giống như singleton-scope tuy nhiên có sự khác biệt quan trọng là scope của application-scope sẽ được shared giữa multipe servlet-based running trên cùng một ServletContext trong khi singleton-scope thì scoped cho một application context.
Tạo một bean application-scope như sau:
@Bean
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public MessageGenerator generateApplicationMessage(){
return new MessageGenerator();
}
Và sử dụng generateApplicationMessag ebean trong controller
@Controller
public class MessageController {
@Resource(name = "generateApplicationMessage")
MessageGenerator generateApplicationMessage;
@RequestMapping("/message/application")
public String getApplicationScopeMessage(final Model model) {
model.addAttribute("previousMessage", generateApplicationMessage.getMessage());
generateApplicationMessage.setMessage("Good Morning!");
model.addAttribute("currentMessage", generateApplicationMessage.getMessage());
return "Example";
}
}
4.4 WebSocket Scope
Khởi tạo websocket-scope bean như sau
@Bean
@Scope(value = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public MessageGenerator generateSocketMessage(){
return new MessageGenerator();
}
WebSocket-scope bean được khởi tạo và lưu trữ tại WebSocket session attributes. Instance return là giống nhau khi có request từ WebSocket session.
5. Link Tham khảo