概述

本文介绍的Spring 中bean的作用域。

问题 :

  • bean的作用域有几种,有那些应用场景

bean 装配过程

下图为bean在容器中从创建到销毁的若干阶段。

bean 作用域

作用域介绍

下面的表格显示的就是bean的作用域,其中单例模式(singleton)下是bean 默认的作用域;prototype 确定一个类,衍生出多个实例。request 和 session 和 http 请求有关;application 的作用域和 ServletContext 有关。

下面展示的是 singleton 和 prototype 两种作用域的示意图。

singleton

prototype

为bean指定作用域

下面是两种方式为bean指定了作用域。

//假如你使用组件扫描发现和声明 bean
@Component
@Scope(ConfigurationBeanFactory.SCOPE_PROTOTYPE)
public class {
....
} <!--使用XML 的方式就像下面所示-->
<bean id="notepad"
class="com.myapp.Notpad"
scope="prototype"
/>

作用域的bean 作为依赖

singleton 和 prototype 作用域的bean 注入到另外的 bean 时不需要使用代理,而request,session 和自定义作用域的bean

作为依赖时需要使用代理。

下面以“购物-购物车”为应用场景为例子。

有一个bean代表用户的购物车。 如果购物车是单例的话, 那么将会导致所有的用户都会向同一个购物车中添加商品。 另一方

面, 如果购物车是原型作用域的, 那么在应用中某一个地方往购物车中添加商品, 在应用的另外一个地方可能就不可用了, 因为在这里

注入的是另外一个原型作用域的购物车。

假设我们要将ShoppingCart bean注入到单例StoreService bean的Setter方法中, 如下所示 :

@Component
public class StoreService{ @Autowired
public void setShoppingCard(ShopperingCar car){
this.shopperingcar = car;
}
}

我们的购物车bean作用域已经确定是 session 的,而StoreService 作用域是 singleton

//购物车bean
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopeProxyMode.INTERFACES)
public ShopperingCart cart(){
...
}
      

可以看到我们发的Scope 注解中出现了一个 proxyMode 的属性,下面解释一下使用这个属性的原因 :

因为StoreService是一个单例的bean, 会在Spring应用上下文加载的时候创建。 当它创建的时候, Spring会试图将ShoppingCart bean注入到 setShoppingCart() 方法中。 但是ShoppingCart bean是会话作用域的, 此时并不存在。 直到某个用户进入系统, 创建了会话之后, 才会出现ShoppingCart实例。

另外, 系统中将会有多个 ShoppingCart 实例: 每个用户一个。 我们并不想让Spring注入某个固定的 ShoppingCart 实例到StoreService 中。 我们希望的是当 StoreService 处理购物车功能时, 它所使用的 ShoppingCart 实例恰好是当前会话所对应的那一个。Spring并不会将实际的 ShoppingCart bean 注入到 StoreService 中, Spring会注入一个到 ShoppingCart bean 的代理, 下图所示。 这个代理会暴露与 ShoppingCart 相同的方法, 所以 StoreService会认为它就是一个购物车。 但是, 当StoreService调用 ShoppingCart 的方法时, 代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。

需要注意的是如果ShoppingCart是一个具体的类的话, Spring就没有办法创建基于接口的代理了。 此时, 它必须使用CGLib来生成基于类的代理。 所以, 如果bean类型是具体类的话, 我们必须要将 proxyMode 属性设置为 ScopedProxyMode.TARGET_CLASS, 以此来表明要以生成目标类扩展的方式创建代理。

下面我们看一下XML 方式的装配 :

<bean id = "card" class="com.myapp.ShoppingCart" scop="session">
<aop:scope-proxy proxy-target-class = "false">
</bean>

注意XML文件需要添加 aop 的命名空间。

参考资料

  • 《Spring in Action》
  • spring.io doc

Spring学习(二)--- Bean 作用域的更多相关文章

  1. spring 学习之 bean 的注入方式 property和constructor-arg的使用方式

    spring 学习之 bean 的注入方式 property和constructor-arg的使用方式. bean的注入方式: property 注入是: 通过setxx方法注入. construct ...

  2. Spring入门(3)-Spring命名空间与Bean作用域

    Spring入门(3)-Spring命名空间与Bean作用域 这篇文章主要介绍Spring的命名空间和Bean作用域 0. 目录 Spring命名空间 Bean作用域 1. Spring命名空间 在前 ...

  3. Spring 学习笔记 Bean的作用域

    在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.在低版本的Spring中,仅有两个作用域 ...

  4. Spring学习(二):Spring支持的5种Bean Scope

    序言 Scope是定义Spring如何创建bean的实例的.Spring容器最初提供了两种bean的scope类型:singleton和prototype,但发布2.0以后,又引入了另外三种scope ...

  5. Spring学习(二)--装配Bean

    一.Spring装配机制 Spring提供了三种主要的装配机制: 1.在XML中进行显示配置 2.在Java中进行显示配置 3.隐式的bean发现机制和自动装配--自动化装配bean Spring可以 ...

  6. Spring学习二:Spring Bean 定义

    Bean 定义 被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的.bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象.这些 bean 是 ...

  7. Spring IOC 之Bean作用域

    当你创建一个bean定义的时候,你创建了一份通过那种bean定义的bean的创建类的真正实力的处方.bean的定义是一个处方 的想法是很重要的的.因为这意味着,对于一个类你可以创建很多对象实例从一个单 ...

  8. Spring系列(二) Bean装配

    创建应用对象之间协作关系的行为称为装配(wiring), 这也是DI的本质. Spring中装配Bean的方式 Spring提供了三种装配Bean的方式. 隐式的Bean发现机制和自动装配 Java ...

  9. Spring之配置文件bean作用域的详细介绍

    Spring的配置文件applicationContext.xml中bean作用域的详细介绍: 1:对象的创建:单例和多例        scope="singleton",默认值 ...

  10. Spring 学习之bean的理解

    前言:对于使用Spring框架的开发人员来说,我们主要做的主要有两件事情:①开发Bean;②配置Bean;而Spring帮我们做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法来完成“依 ...

随机推荐

  1. static修饰的方法不能被重写可以被继承

    今天我们谈谈为什么抽象类中不能有静态的抽象方法以及static修饰的方法不能被重写可以被继承 1 static修饰的方法不能被重写可以被继承我们知道static修饰的方法为静态方法,可以直接使用类名. ...

  2. 高性能缓存服务器Varnish

    一.Varnish概述 Varnish是一款高性能的.开源的反向代理服务器和缓存服务器,计算机系统的除了有内存外,还有CPU的L1.L2,甚至L3级别的缓存,Varnish的设计架构就是利用操作系统的 ...

  3. Python 的 GIL 是什么鬼,多线程性能究竟如何

    作者:卢钧轶(cenalulu) 本文原文地址: http://cenalulu.github.io/python/gil-in-python/ 前言:博主在刚接触Python的时候时常听到GIL这个 ...

  4. js中数组的操作方法

    今天给大家带来一篇有关数组操作方法的文章. 新建数组 方法一:通过new运算符创建一个数组构造函数. var arr = new Array(); 方法二:通过方括号直接创建直接量数组. var ar ...

  5. ReactNative常用组件库 victory-native 图表

    victory-native 是不错的图表组件,支持很多种图表 地址: https://github.com/FormidableLabs/victory-native 先安装 react-nativ ...

  6. centos6.5安装docker(亲测)

    centos6.5下安装docker的过程办法 在看了网上N多复制粘贴的文章,又尝试无效后,我把我最终成功的办法发出来,希望能帮到拼命干环境的你. 操作环境: centos6.5(Final) 内核: ...

  7. mariadb(mysql)的安装

    1 使用官方源安装mariadb vim /etc/yum.repos.d/MariaDB.repo 添加repo仓库配置内容 [mariadb] name=MariaDB baseurl=http: ...

  8. 等价类计数问题(Polya定理和burnside引理)

    零.约定: (置换等名词会在前置知识中有解释) \(1.\)在本文中,题目要求的染色方案等统称为"元素". \(2.\)两个元素严格相等我们记做"\(=\)", ...

  9. Mac下安装Fiddler抓包工具(别试了,会报错,没办法使用)

    下载: https://www.telerik.com/download/fiddler 离线版本:(链接: https://pan.baidu.com/s/1hr7f8QK 密码: ukg2) 安装 ...

  10. python并发学习总结

    目录 一.理解操作系统 二.任务类型 三.Socket模块 四.一个简单的C/S程序 五.使用阻塞IO实现并发 方案一:阻塞IO+多进程 方案二:阻塞IO+多线程 阻塞IO模型的思考和总结 六.使用非 ...