SpringInAction--Bean的作用域
Spring定义了多种作用域,我们在使用的时候可以根据使用的需求来选择对应的作用域,这些作用域,包括(第二个括号中为更安全的注解方法,具体更多参数可查看接口代码)
- 单例(Singleton)(ConfigurableBeanFactory.SCOPE_SINGLETON):在整个应用中,只创建bean的一个实例。
- 原型(Prototype)(ConfigurableBeanFactory.SCOPE_PROTOTYPE):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
- 会话(Session)(WebApplicationContext.SCOPE_SESSION):在Web应用中,为每个会话创建一个bean实例。
- 请求(Rquest)(WebApplicationContext.SCOPE_REQUEST):在Web应用中,为每个请求创建一个bean实例。
单例是默认的作用域,但是正如之前所述,对于易变的类型,这并不合适。如果选择其他的作用域,要使用@Scope注解,它可以与@Component或@Bean一起使用。
我们可以分别使用三种配置Bean的方法来指定Bean的作用域。
使用隐式的组件扫描方式:
@Component
@Scope("prototype")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DangNianQing implements CompactDisc {
}
}
使用java方式配置
@Bean
@Scope("prototype")
public CDPlay cdPlay(CompactDisc compactDisc){
return new CDPlay(compactDisc);
}
使用xml方式配置
<bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="prototype"/>
假如我们现在正在做一个购物的网站,就购物车这个Bean来说,如果没有指定他的作用于的话,那么就是默认的单例模式,那么就会发生:所有的用户都会向同一个购物车中添加商品。另一方面,如果购物车是原型作用域的,那么在应用中某一个地方往购物车中添加商品,在应用的另外一个地方可能就不可用了,因为在这里注入的是另外一个原型作用域的购物车。所以这个时候,最适合的就是用会话作用域。
使用的方法是:
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.INTERFACES)
public ShoppingCar cart(){ }
正好有个Service,有个Setter方法需要注入Bean
@Component
public class storeService{
@Autowired
public void setShoppingCar(ShoppingCar shoppingCar){
this.shoppingCar = shoppingCar;
}
}
从上面的代码中我们可以看出storeService是默认的 为单例Bean,会在Spring应用上下文加载的时候创建,当然在创建的时候也会企图去将ShoppingCar注入进来,但是ShoppingCart bean是会话作用域的,此时并不存在。直到某个用户进入系统,创建了会话之后,才会出现ShoppingCart实例。另外,系统中将会有多个ShoppingCart实例:每个用户一个。我们并不想让Spring注入某个固定的ShoppingCart实例到StoreService中。我们希望的是当StoreService处理购物车功能时,它所使用的ShoppingCart实例恰好是当前会话所对应的那一个。
但是在这个例子当中Spring并不会将实际的ShoppingCart bean注入到StoreService中,Spring会注入一个到ShoppingCart bean的代理,如下图所示。这个代理会暴露与ShoppingCart相同的方法,所以StoreService会认为它就是一个购物车。但是,当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。
现在,我们带着对这个作用域的理解,讨论一下proxyMode属性。如配置所示,proxyMode属性被设置成了copedProxyMode.INTERFACES,这表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean。
如果ShoppingCart是接口而不是类的话,这是可以的(也是最为理想的代理模式)。但如果ShoppingCart是一个具体的类的话,Spring就没有办法创建基于接口的代理了。此时,它必须使用CGLib来生成基于类的代理。所以,如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理。
下面也学习下在xml中配置作用域的代理
<bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="session">
<aop:scoped-proxy></aop:scoped-proxy>
</bean>
其中的<aop:scoped-proxy>与@Scope中的proxyMode 一样的,因为Bean类型是类 不是接口所以要把 proxy-target-class属性设置为false
<bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="session">
<aop:scoped-proxy proxy-target-class="false" />
</bean>
总的来说:就是如果我们有一个接口或者类 需要注入Bean的时候,我们可以委托给代理,这样就每次请求会话的时候,都有一个与其对应的Bean了
以上就是Bean作用域相关的知识,如果有错误,请指出,谢谢
SpringInAction--Bean的作用域的更多相关文章
- spring实战三装配bean之Bean的作用域以及初始化和销毁Bean
1.Bean的作用域 所有的spring bean默认都是单例.当容器分配一个Bean时,不论是通过装配还是调用容器的getBean()方法,它总是返回Bean的同一个实例.有时候需要每次请求时都获得 ...
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Spring bean的作用域和生命周期
bean的作用域 1.singleton,prototype, web环境下:request,session,gloab session 2.通过scope="" 来进行配置 3. ...
- Bean 的作用域
•在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域. 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实 ...
- [原创]java WEB学习笔记99:Spring学习---Spring Bean配置:自动装配,配置bean之间的关系(继承/依赖),bean的作用域(singleton,prototype,web环境作用域),使用外部属性文件
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Bean的作用域及生命周期
指定bean的作用域通过scope属性 singleton单实例模式,从初始化容器就初始化bean,除非延迟初始化lazy-init=true prototype每次从容器获取bean是新的对象,从g ...
- Spring基础—— Bean 的作用域
一.在 Spring Config 文件中,在 <bean> 元素的 scope 属性里设置 Bean 的作用域.默认为 singleton ,单例的. 二.在不引入 spring-web ...
- bean的作用域
bean的作用域为singleton,spring容器中只存在一个bean的实例,所有对该bean的请求只返回同一个bean实例. 当bean的作用域为prototype时,每一次对bean的请求,都 ...
- DI 之 3.4 Bean的作用域(捌)
3.4 Bean的作用域 什么是作用域呢?即"scope",在面向对象程序设计中一般指对象或变量之间的可见范围.而在Spring容器中是指其创建的Bean对象相对于其他Bean对 ...
- spring之bean的作用域scope的值的详解
今天研究了一下scope的作用域.默认是单例模式,即 scope="singleton".另外scope还有prototype.request.session.global ses ...
随机推荐
- GRUB2 分析 (三)
接上一篇 从地址0x8200开始的是lzma_decompress.img.这是由startup_raw.S编译生成的.这个文件稍微复杂点.首先一开始就是个跳转指令: ljmp $0, $ABS(LO ...
- 如何用纯 CSS 创作气泡填色的按钮特效
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/eKqZjy 可交互视频 ...
- Java学习第一周博客
20145307<Java程序设计>第一周学习总结 教材学习内容总结 首先学习安装Java有两种方法,一种是用Eclipse直接编辑输出,另一种方法是用记事本之后用win+G开启cmd运行 ...
- Spring事务管理之几种方式实现事务
1.事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...
- Linux kernel 编译问题记录【转】
本文转载自:http://sunyongfeng.com/201701/programmer/linux/kernel_compile_fail.html 编译内核出现以下错误 Can't use ' ...
- [CF730J]Bottles
题目大意:每个瓶子有一定的容积,以及一定的水量,问最少几个瓶子装满所有水,在此基础上还要最小化移动水的体积 第一问用贪心直接求第二问转化成背包问题设dp[i][j]表示前i桶水总容积为j的最多水量,这 ...
- 1970年1月1日(00:00:00 GMT)Unix 时间戳(Unix Timestamp)
转载自(http://jm.ncxyol.com/post-88.html) 今天在看Python API时,看到time模块: The epoch is the point where the ...
- Import SQL into MySQL with a progress meter
There is nice tool called pv # On Ubuntu/Debian system $ sudo apt-get install pv # On Redhat/CentOS ...
- sql server 数据字典的妙用
以下提到的一些需求,你可能会说用SQL server management studio 客户端 看一下不就可以了,何必这么麻烦 ! 是的,当1 个表的时候我们可以人工检查,但当有10 个表,100个 ...
- ThinkPHP开发笔记-模型
1.模型定义.在ThinkPHP中,可以无需进行任何模型定义.只有在需要封装单独的业务逻辑的时候,模型类才是必须被定义的,因此ThinkPHP在模型上有很多的灵活和方便性,让你无需因为表太多而烦恼. ...