Spring_总结_04_高级配置(四)_bean的作用域
一、前言
本文承接上一节:Spring_总结_04_高级配置(三)之处理歧义
1.单例bean
Spring应用上下文中所有的bean默认都是单例的。也就是说,不管一个bean被注入到其他bean多少次,每次注入的都是同一个实例。
2.有状态bean与无状态bean
单例bean适用于那些无状态的对象,在多数情况下,单例bean是很理想的方案。但是有时候,你所使用的类是易变的,他会保持一些状态(有状态),因此重用是不安全的。
举个例子:
这段时间在做一个脚本引擎,需要在java中执行js代码。当我在程序中注入一个单例的脚本引擎,并用这个脚本引擎去重复执行一段js代码。
第一次执行的时候,能正常执行;第二次执行的时候,却报js中定义的一个对象已存在。
这就是因为在第二次执行的时候,单例的脚本引擎中已经包含了第一次执行时的状态,即第一次执行之后,js中的对象已存在于脚本引擎中,因此导致第二次执行时出现重复定义的错误。
在这个例子中,我们需要的其实是,每次执行的时候单独为我创建一个bean,而不是每次使用的都是同一个bean。
二、bean的作用域
Spring定义了多种作用域,可以基于这些作用域创建bean。
1 | 单例(Singleton) | 在整个应用中,只创建bean的一个实例 |
2 | 原型(Prototype) | 每次注入或者通过Spring应用上下文获取的时候,都会一个新的bean实例。 |
3 | 会话(Session) | 在Web应用中,为每个会话创建一个bean实例 |
4 | 请求(Request) | 在Web应用中,为每个请求创建一个bean实例 |
单例是默认的作用域,这对于易变类型,并不合适,这是就要为bean声明一个@Scope注解,可配合@Component或@Bean一起使用。
1.Prototype
为bean声明如下注解,即可创建原型bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
或者
@Scope("prototype")
示例如下:
(1)自动装配时
@Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Notepad{...}
(2) Java 配置时
@Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public Notepad notepad(){ return new Notepad(); }
(3) xml 配置
<bean id="notepad" class="com.myapp.Notepad" scope="prototype" />
2.Session
为bean声明如下注解,即可创建会话bean
@Component @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS) public ShoppingCart cart(){...}
假设,我们要将ShoppingCart bean 注入到单例 StoreService bean的 Setter方法中,如下所示:
@Coponent public class StoreService{ @Autowired public void setShoppingCart( ShoppingCart shoppingCart){ this.shoppingCart = shoppingCart; } }
因为storeService是一个单例bean,会在Spring应用上下文加载的时候创建。当它创建的时候,Spring会注入一个到ShoppingCart的代理。当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。
注意到proxyMode属性,ScopedProxyMode.TARGET_CLASS 表明将创建一个基于目标类的代理。
而若ShoppingCart是一个接口时,则需要使用 ScopedProxyMode.INTERFACES,表明要创建一个实现ShoppingCart接口的代理,并将调用委托给实现bean。
3.Request
为bean声明如下注解,即可创建请求bean
@Component @Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.TARGET_CLASS) public ShoppingCart cart(){...}
三、参考资料
1.《Spring 实战 (第四版)》