在默认情况下,Spring应用上下文中所有bean都是作为以单例(singleton)的形式创建的。也就是说,不管给定的一个bean被注入到其他bean多少次,每次所注入的都是同一个实例。
Spring定义了多种作用域,可以基于这些作用域创建bean,包括:
- 单例(Singleton):在整个应用中,只创建bean的一个实例。
- 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
- 会话(Session):在Web应用中,为每个会话创建一个bean实例。
- 请求(Rquest):在Web应用中,为每个请求创建一个bean实例。
如果使用组件扫描来发现和声明bean,则可以使用 @Scope 注解指定bean的作用域,如:
@Scope("prototype")
@Component
public class test { ... }
如果使用xml配置bean,则可以使用<bean>元素的scope属性来设置作用域,如:
<bean id="test" class="com.bean.Test" scope="prototype" />
会话和请求作用域
如果我们希望不是所有用户都使用同一个bean,并且对于同一个用户来说,bean是单例的,那么可以使用会话作用域,即@Scope("session")
在这里@Scope还有一个proxyMode属性,这个属性解决了将会话或请求作用域的bean注入到单例bean中所遇到的问题。
假设我们有一个购物车ShoppingCart ,将其bean注入到单例的StoreService的Setter方法中,如:
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart() { ... }
@Component
public class StoreService {
@Autowired
public void setShoppingCart(ShoppingCart shoppingCart) {
this.shoppingCart = shoppingCart;
}
}
StoreService是一个单例的bean,会在Spring应用上下文加载的时候创建。当创建的时候,Spring会尝试将ShoppingCart bean注入,但是由于ShoppingCart是会话作用域的,此时并不存在,只有当用户进入系统,创建了会话才会出现ShoppingCart实例。
每个用户都有一个ShoppingCart实例。我们并不希望其注入到某个固定的ShoppingCart实例到StoreService中
Spring并不会将实际的ShoppingCart注入到StoreService中,Spring会注入一个ShoppingCart bean的代理
网友评论