【Spring】3.4、bean的作用域
默认情况下,bean是单例的形式创建的,既整个应用程序使用的bean是同一个实例。
有些情况,如果想重用这个bean,结果这个bean被之前的操作污染了,会使程序发生错误。
Spring支持为bean设置作用域,提供了以下几种作用域:
单例(Singleton):整个应用中,只创建bean的一个实例。
原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
会话(Session):Web应用中,为每个会话创建一个bean实例。
请求(Request):Web应用中,为每个请求创建一个bean实例。
//可以使用组件扫描时,声明作用域;作用域可以使用ConfigurableBeanFactory表示 @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Cake implements Dessert{...} //可以在Java配置Bean时,声明作用域;作用域也可以使用字符串表示,不过建议使用ConfigurableBeanFactory更不容易出错 @Bean @Scope("prototype") public Dessert iceCream{ return new IceCream(); }
<!-- 使用XML配置时,设置bean作用域 --> <bean id="iceCream" class="com.desserteater.IceCream" scope="prototype" />
使用会话和请求作用域
某些情景下,某个bean(例如Web应用中的购物车bean),不应该是对于程序单例的,而是对于每一个用户有对应一个bean。
这种情况下,适合使用会话作用域的bean
@Component @Scope( value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES) public ShopingCart cart(){...}
WebApplicationContext:SCOPE_SESSION属性表明Spring为每一个Web会话创建一个实例
ScopedProxyMode:解决会话作用域的bean注入到单例bean的问题。当会话作用域的bean注入到单例bean的时候,Spring改为注入一个bean代理,当单例bean需要调用会话作用域的bean时,该代理才针对当前会话,找到对应的bean,进行调用。
ScopedProxyMode.INTERFACES:当该bean是一个接口的时候,设置值为INTERFACES,表示该代理要实现该接口,并讲调用委托给实现的bean。
ScopedProxyMode.TARGET_CLASS:当该bean是一个类的时候,设置值为TARGET_CLASS,因为SPring无法创建基于接口的代理,需要使用CGLib来生成基于类的代理,通过生成目标类扩展的方式来进行代理。
同样,请求作用域也是有一样的问题,同样处理即可。
在XML中声明作用域代理
引用aop命名空间
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-beans.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context"> <!-- 配置内容 --> </beans>
使用aop命名控件声明作用域代理:
<aop:scoped-proxy />是和@Scope注解的proxyMode属性相同的XML元素
它告诉Spring为bean创建一个作用域代理,默认状态下,会使用CGLib创建目标类代理。
<bean id="cart" class="com.myapp.ShoppingCart" scope="session"> <aop:scoped-proxy /> </bean>
设置为生成基于接口的代理
<bean id="cart" class="com.myapp.ShoppingCart" scope="session"> <aop:scoped-proxy proxy-target-class="false" /> </bean>
浙公网安备 33010602011771号