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的作用域。

使用隐式的组件扫描方式:

  1. @Component
  2. @Scope("prototype")
  3. //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  4. public class DangNianQing implements CompactDisc {
  5. }
  6. }

使用java方式配置

  1. @Bean
  2. @Scope("prototype")
  3. public CDPlay cdPlay(CompactDisc compactDisc){
  4. return new CDPlay(compactDisc);
  5. }

使用xml方式配置

  1. <bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="prototype"/>

假如我们现在正在做一个购物的网站,就购物车这个Bean来说,如果没有指定他的作用于的话,那么就是默认的单例模式,那么就会发生:所有的用户都会向同一个购物车中添加商品。另一方面,如果购物车是原型作用域的,那么在应用中某一个地方往购物车中添加商品,在应用的另外一个地方可能就不可用了,因为在这里注入的是另外一个原型作用域的购物车。所以这个时候,最适合的就是用会话作用域。

使用的方法是:

  1. @Component
  2. @Scope(value = WebApplicationContext.SCOPE_SESSION,
  3. proxyMode = ScopedProxyMode.INTERFACES)
  4. public ShoppingCar cart(){
  5.  
  6. }

正好有个Service,有个Setter方法需要注入Bean

  1. @Component
  2. public class storeService{
  3. @Autowired
  4. public void setShoppingCar(ShoppingCar shoppingCar){
  5. this.shoppingCar = shoppingCar;
  6. }
  7. }

从上面的代码中我们可以看出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中配置作用域的代理

  1. <bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="session">
  2. <aop:scoped-proxy></aop:scoped-proxy>
  3. </bean>

其中的<aop:scoped-proxy>与@Scope中的proxyMode 一样的,因为Bean类型是类 不是接口所以要把 proxy-target-class属性设置为false

  1. <bean id="dangNianQing" class="com.bean.xml.DangNianQing" scope="session">
  2. <aop:scoped-proxy proxy-target-class="false" />
  3. </bean>

总的来说:就是如果我们有一个接口或者类 需要注入Bean的时候,我们可以委托给代理,这样就每次请求会话的时候,都有一个与其对应的Bean了

以上就是Bean作用域相关的知识,如果有错误,请指出,谢谢

SpringInAction--Bean的作用域的更多相关文章

  1. spring实战三装配bean之Bean的作用域以及初始化和销毁Bean

    1.Bean的作用域 所有的spring bean默认都是单例.当容器分配一个Bean时,不论是通过装配还是调用容器的getBean()方法,它总是返回Bean的同一个实例.有时候需要每次请求时都获得 ...

  2. Spring中Bean的作用域、生命周期

                                   Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...

  3. Spring bean的作用域和生命周期

    bean的作用域 1.singleton,prototype, web环境下:request,session,gloab session 2.通过scope="" 来进行配置 3. ...

  4. Bean 的作用域

    •在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域. 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实 ...

  5. [原创]java WEB学习笔记99:Spring学习---Spring Bean配置:自动装配,配置bean之间的关系(继承/依赖),bean的作用域(singleton,prototype,web环境作用域),使用外部属性文件

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. Bean的作用域及生命周期

    指定bean的作用域通过scope属性 singleton单实例模式,从初始化容器就初始化bean,除非延迟初始化lazy-init=true prototype每次从容器获取bean是新的对象,从g ...

  7. Spring基础—— Bean 的作用域

    一.在 Spring Config 文件中,在 <bean> 元素的 scope 属性里设置 Bean 的作用域.默认为 singleton ,单例的. 二.在不引入 spring-web ...

  8. bean的作用域

    bean的作用域为singleton,spring容器中只存在一个bean的实例,所有对该bean的请求只返回同一个bean实例. 当bean的作用域为prototype时,每一次对bean的请求,都 ...

  9. DI 之 3.4 Bean的作用域(捌)

    3.4  Bean的作用域 什么是作用域呢?即"scope",在面向对象程序设计中一般指对象或变量之间的可见范围.而在Spring容器中是指其创建的Bean对象相对于其他Bean对 ...

  10. spring之bean的作用域scope的值的详解

    今天研究了一下scope的作用域.默认是单例模式,即 scope="singleton".另外scope还有prototype.request.session.global ses ...

随机推荐

  1. LigerUI ligerComboBox 下拉框 表格 多选无效

    $("#txt1").ligerComboBox({ width: 250, slide: false, selectBoxWidth: 500, selectBoxHeight: ...

  2. Git笔记之初识vi编辑器

    1.vi编辑器 如同Windows下的记事本,vi编辑器是Linux下的标配,通过它我们可以创建.编辑文件.它是一个随系统一起安装的文本编辑软件. vi编辑器提供了3种模式,分别是命令模式.插入模式. ...

  3. redis:Invalid input of type: 'bool' type. Convert to a byte,string or number first

    分析:出现此错误的原因是redis版本过高导致的,因此降低redis版本即可 解决: pip install -U redis==2.10.6

  4. 爬虫之Requests: 让 HTTP 服务人类

    Requests: 让 HTTP 服务人类 虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “ ...

  5. spark(二)优化思路

    优化思路 内存优化 内存优化大概分为三个方向 1.所有对象的总内存(包括数据和java对象) 2.访问这些对象的开销 3.垃圾回收的开销 其中Java的原生对象往往都能被很快的访问,但是会多占据2-5 ...

  6. oracle in语句的坑

    oracle 的in语句最多只能有1000条数据,超出,sql报错.

  7. 简单的使用hibernate插入数据的例子

    数据库创建脚本: drop table person create table person( id          varchar(32)         not null primary key ...

  8. Spark 基于物品的协同过滤算法实现

    J由于 Spark MLlib 中协同过滤算法只提供了基于模型的协同过滤算法,在网上也没有找到有很好的实现,所以尝试自己实现基于物品的协同过滤算法(使用余弦相似度距离) 算法介绍 基于物品的协同过滤算 ...

  9. js三种对话框

    <html> <head> <script> function tip1(){ //这个基本没有什么说的,就是弹出一个提醒的对话框 alert("这个第一 ...

  10. 基础系列(1)之干掉JavaScript变量作用域

     今天去某顺公司面试,发现一些基础知识都不记得了,于是乎决定把js基础系列的全部梳理一遍,今天就整理下js变量作用域的相关基础知识点,配合最常遇到的笔试题阐述. 题一: var g = "a ...