Bean 的作用域种类
在 Spring 中⽀持 6 种作⽤域,后 4 种在 Spring MVC 环境才⽣效
1. singleton:单例作⽤域
2. prototype:原型作⽤域(多例作⽤域)
3. request:请求作⽤域
4. session:会话作⽤域
5. application:全局作⽤域
6. websocket:HTTP WebSocket 作⽤域
作用域及其含义
参考文档:https://docs.spring.io/spring-framework/reference/core/beans/factory-scopes.html
代码实现
// Bean 作用域的配置
@Configuration
public class BeanConfig {// Bean 的默认作用域,单例模式@Beanpublic User user(){return new User();}//作用域: singleton 单例模式//每个 Spring IoC 容器内同名称的 bean 只有⼀个实例(单例)(默认)@Bean@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)public User singletonUser(){return new User();}//作用域:prototype 原型(非单例)//每次获取 bean 时会创建新的实例(⾮单例)@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public User prototypeUser(){return new User();}//作用域:request 请求//每个 HTTP 请求⽣命周期内,创建新的实例(web环境中)@Bean@RequestScopepublic User requestUser(){return new User();}//作用域:session 会话//每个 HTTP Session ⽣命周期内,创建新的实例(web环境中)@Bean@SessionScopepublic User sessionUser(){return new User();}//作用域:application 应用@Bean@ApplicationScopepublic User applicationUser(){return new User();}
}
@RequestScope 等同于 @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@SessionScope 等同于 @Scope(value =WebApplicationContext.SCOPE_SESSION, proxyMode =ScopedProxyMode.TARGET_CLASS)
@ApplicationScope 等同于 @Scope(value =WebApplicationContext.SCOPE_APPLICATION, proxyMode =ScopedProxyMode.TARGET_CLASS)
proxyMode⽤来为 spring bean 设置代理. proxyMode = ScopedProxyMode.TARGET_CLASS 表⽰这个 Bean 基于 CGLIB 实现动态代理.Request,session和 application 作⽤域的 Bean 需要设置 proxyMode
测试不同作用域的 Bean 取到的对象是否⼀样
@RestController
@RequestMapping("/Bean")
public class BeanController {//默认作用域下获取的对象@Qualifier("user") //设置注入对象的名称@Autowiredprivate User defaultBean;//作用域为单例(singleton)时获取的对象@Qualifier("singletonUser")@Autowiredprivate User singletonBean;//作用域为原型(prototype)时获取的对象@Qualifier("prototypeUser") //设置注入对象的名称@Autowiredprivate User prototypeBean;//作用域为 HTTP 请求(request)时获取的对象@Qualifier("requestUser") //设置注入对象的名称@Autowiredprivate User requestBean;//作用域为会话(session)时获取的对象@Qualifier("sessionUser") //设置注入对象的名称@Autowiredprivate User sessionBean;//作用域为 ServletContext⽣命周期内(application)时获取的对象@Qualifier("applicationUser") //设置注入对象的名称@Autowiredprivate User applicationBean;//注入 Spring 的 IoC 容器,注意 applicationContext 导入的包是 springframework 的@Autowiredprivate ApplicationContext applicationContext;//默认作用域下获取的对象@RequestMapping("/default")public String defaultBean(){User contextBean=(User) applicationContext.getBean("user");return "默认作用域下,注入的对象为:"+defaultBean+"在 context 容器中获取的对象为:"+contextBean;}//作用域为单例(singleton)时获取的对象@RequestMapping("/singleton")public String singletonBean(){User contextBean=(User) applicationContext.getBean("singletonUser");return "单例(singleton)作用域下,注入的对象为:"+singletonBean+"在 context 容器中获取的对象为:"+contextBean;}//作用域为原型(prototype)时获取的对象@RequestMapping("/prototype")public String prototypeBean(){User contextBean=(User) applicationContext.getBean("prototypeUser");return "原型(prototype)作用域下,注入的对象为:"+prototypeBean+"在 context 容器中获取的对象为:"+contextBean;}//作用域为 HTTP 请求(request)时获取的对象@RequestMapping("/request")public String requestBean(){User contextBean=(User) applicationContext.getBean("requestUser");return "request 请求作用域下,注入的对象为:"+requestBean+"在 context 容器中获取的对象为:"+contextBean;}//作用域为会话(Session)时获取的对象@RequestMapping("/session")public String sessionBean(){User contextBean=(User) applicationContext.getBean("sessionUser");return "session 会话作用域下,注入的对象为:"+sessionBean+"在 context 容器中获取的对象为:"+contextBean;}//作用域为应用(application)时获取的对象@RequestMapping("/application")public String applicationBean(){User contextBean=(User) applicationContext.getBean("applicationUser");return "application 应用作用域下,注入的对象为:"+applicationBean+"在 context 容器中获取的对象为:"+contextBean;}
}
观察 Bean 的作用域
单例作用域(singleton)
默认就是单例作用域,所以默认情况下和单例( singleton)作用域下,多次访问,得到的都是同⼀个对象,并且 @Autowired 和 applicationContext.getBean() 也是同⼀个对象.
原型作用域(prototype)
每次获取的对象都不⼀样(注⼊的对象在 Spring 容器启动时,就已经注⼊了,所以多次请求也不会发⽣变化)
请求作⽤域(request)
在⼀次请求中,@Autowired 和 applicationContext.getBean() 也是同⼀个对象. 但是每次请求,都会重新创建对象
会话作⽤域(session)
在⼀个 session 中,多次请求,获取到的对象都是同⼀个.
换⼀个浏览器访问,发现会重新创建对象.(另⼀个 Session )
应用作⽤域(application)
在⼀个应⽤中,多次访问都是同⼀个对象
Application 和 singleton 的区别
Application scope就是对于整个 web 容器来说,bean 的作⽤域是 ServletContext 级别的.这个和 singleton有点类似,区别在于: Application scope是 ServletContext 的单例, singleton 是⼀个 ApplicationContext 的单例.在⼀个 web 容器中 ApplicationContext 可以有多个.(了解即可)