spring的bean作用域详解

相信使用过spring框架的 都接触过了解过spring bean的概念,它与java 的bean有所不同。springBean存在作用域这一概念。


相信大家对于@Scope这个注解一定不会陌生。

在默认情况下,springIOC中所有的bean都是以单例(singleton)的形式创建的,也就是说,不管给定的一个bean被注入到其他bean中多少次,每次所注入的都是全局唯一的一个实例。

这个默认情况在大多数场景中都是很理想的一个方案,这样系统对于bean的管理和对象的垃圾回收成本都会很小。

但是在一些情况下,可能就会出现些许问题。例如,我所注入的这个类是易变的,它的某个成员变量作为状态信息,需要被保持,因此不能再在任意的重用它了(这会导致状态值的改变)。这种情况下,singleton就不是什么好主意了。

对此,spring定义了多种作用域,可以基于业务场景灵活调整:

1.单例(singleton):在整个应用中,只会创建bean的一个实例

2.原型(prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean实例

3.会话(Session):在Web应用中,为每个会话创建一个bean实例

4.请求(Request):在Web应用中,为每个请求创建一个bean实例

要更改bean的作用域,可以使用@Scope注解

该注解可以加在类上(基于组件扫描来装配bean的模式)和方法上(基于javaConfig来装配bean的模式)

ConfigurableBeanFactory.SCOPE_PROTOTYPE定义了原型作用域的常量,推荐使用


如果使用xml的方式来配置bean的话,可以使用<bean>元素的scope属性来设置作用域

<bean id="test" class="com.myapp.Test" scope="prototype">
</bean>


 相应的ConfigurableBeanFactory.SCOPE_SESSION和ConfigurableBeanFactory.SCOPE_REQUEST分别定义了会话作用域和请求作用域的常量,

需要注意一点的是,在使用会话作用域和请求作用域时,应在scope上加入proxyMode参数,否则会出现如下问题:

当你试图向一个单例模式的bean注入一个会话模式的bean时,会出现异常,因为该会话模式的bean只会在会话发起时创建,而当单例模式的bean初始化时,该会话模式的bean并不存在。

proxyMode参数的解决方法是,为这个待注入的bean添加一个代理,这个代理具备与原bean相同的方法,以“蒙蔽”初始化的检查。当原bean真正被调用时,代理会解析并调用委托给真正的bean。详细解答参考 java动态代理技术

一般 跑proxyMode参数有两个值,ScopedProxyMode.INTERFACES和ScopedProxyMode.TARGET_CLASS,前者为默认值,使用基于接口的代理,代理的bean需要为接口类型。后者使用基于CGLib来实现类的代理,若代理的bean是具体的类的话,需要设置此类型。


当你使用xml配置时,可以在<bean>元素内使用<aop>标识 来启用作用域代理。例如:

<bean id="test" class="com.myapp.Test" scope="session">
<aop:scope-proxy proxy-target-class="false" />
</bean>
当proxy-target-class为true时,将开启CGLib的类代理,否则执行接口代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值