在配置文件中定义Bean时,用户不但可以配置Bean的属性值及相互之间的依赖关系,还可以定义Bean的作用域。作用域将对Bean的生命周期和创建方式产生影响。
spring 4.0中所支持的作用域:
① singleton:
在Spring IoC容器中仅存在一个Bean实例,Bean以单例的方式存在。
② prototype:
每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时相当于执行new xxxBean()操作。
③ request:
每次HTTP请求都会创建一个新的Bean。该作用域仅适用于WebApplicationContext环境。
④ session:
同一个HTTP session共享一个Bean,该作用域仅适用于WebApplicationContext环境。
⑤ globalSession:
同一个全局session共享一个Bean,一般用于Portlet应用环境。该作用域仅适用于WebApplicationContext环境。

在低版本的Spring中,仅支持两个Bean的作用域,所以采用singleton="true|false"的配置方式。Spring为了向后兼容,依然支持这种方式。不过Spring推荐采用新的配置方式<bean id="xxx" scope="作用域类型">。
除了以上5中预定义的Bean作用域以外,Spring还允许用户自定义Bean的作用域。可以通过org.springframework.beans.factory.config.CustomScopeConfigurer这个BeanFactoryPostProcessor注册自定义的Bean作用域。感兴趣的可以自行阅读Scope接口的javadoc文档。

1 singleton作用域

单例模式是最重要的设计模式之一。在传统的应用开发中,需要手工为每个单实例类编写特定代码,在这种情况下,类的业务逻辑代码和模式代码紧密耦合在一起。Spring以容器的方式提供天然的单例模式功能,任何POJO无需编写特殊的代码,仅通过配置就可以使用单例模式。
一般情况下,无状态或者状态不可变的类适合使用单例模式,不过Spring对此实现了超越。在传统开发中,由于DAO类持有Connection这个非线程安全的变量,因此往往未采用单例模式。而在Spring中,所有的DAO类都可以采用单例模式,因为Spring利用AOP和LocalThread功能,对非线程安全的变量进行了特殊处理,使这些非线程安全的类变成了线程安全的类。
因为Spring的这一超越,所以在实际应用中大部分Bean都能以单例的方式运行,这也是为什么Spring将Bean的默认作用域定位singleton的原因。
singleton的Bean在同一Spring IoC容器中只有一个实例。
不但在配置文件中通过bean的属性注入的bean引用是单例的,任何通过容器的getBean("beanId")方法获取的实例也指向同一个Bean。
在默认的情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中。虽然启动时会花费一些时间,但它带来两个好处:首先,对Bean提前进行实例化操作会及早发现一些潜在的配置问题;其次,Bean以缓存的方式保存,当运行时用到该Bean时就无需在实例化了,提高了运行的效率。如果用户不希望在容器启动时提前实例化singleton的Bean,则可以通过lazy-init属性进行控制。
lazy-init="true" 的Bean在某些情况下依然会提前实例化:如果该Bean被其他需要提前实例化的Bean所引用,那么Spring将会忽略延迟实例化的设置。

2 prototype作用域

采用scope="prototype"指定非单例作用域的Bean,每次通过容器的getBean("beanId")方法返回的都是一个新的实例。
在默认情况下,Spring容器在启动时不实例化prototype的Bean。此外,Spring容器将prototype的Bean交给调用者后,就不在管理它的生命周期。

3 与Web应用环境相关的Bean作用域

如果用户使用Spring的WebApplicationContext,则可以使用另外的3种Bean的作用域:request、session、globalSession。不过在使用这些作用域之前,首先要在Web容器中进行一些额外的配置。

① 在web.xml中添加HTTP请求监听器进行配置:

<web-app><listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener>
</web-app>

大家可能会发现之前WebApplicationContext初始化时,已经通过ContextLoaderListener或ContextLoaderServlet将Web容器与Spring容器进行了整合,为什么在这里又要额外的引入RequestContextListener以支持Bean的另外3个作用域呢?
在整合Spring容器时使用ContextLoaderListener,它实现了ServletContextListener监听器接口,ServletContextListener只负责监听Web容器启动和关闭事件。而RequestContextListener实现了ServletRequestListener监听器接口,该监听器监听了HTTP请求事件,Web服务器接收的每一次请求都会通知该监听器。
Spring容器启动和关闭操作由Web容器的启动和关闭事件触发,但如果Spring容器中的Bean需要request、session和globaalSession作用域的支持,Spring容器本身就必须获得Web容器的HTTP请求事件,以HTTP请求事件驱动Bean作用域的控制逻辑。也就是说通过配置RequestContextListener,Spring容器和Web容器的结合更加密切,Spring容器对Web容器就可以实施相应的Bean作用域控制了。

② request作用域

request作用域的Bean对应一个HTTP请求和声明周期:scope="request" 。
这样,每次HTTP请求调用的Bean,Spring容器都会创建一个新的Bean,请求处理完毕后,就会销毁这个Bean。

③ session作用域

当Bean的作用域为session作用域时,此Bean的作用域在整个HTTP Session中的所有HTTP请求都共享一个Bean。当HTTP Session结束后,Bean被销毁:scope="session"。

④ globalSession作用域

globalSession作用域类似于session作用域,不过仅在Portlet的Web应用中使用。Portlet规范定义了全局Session的概念,它被组成PortletWeb应用的所有子Portlet共享。如果不在PortletWeb应用华静霞,那么globalSession作用域就等价于session作用域。

4 作用域依赖问题

假设将Web相关作用域的Bean注入singleton或prototype的Bean中,我们当然希望它能够按照预定的方式工作,即引用者应该从指定的域中取得它的引用。但如果没有进行一些额外的配置,那么它的运行不会按照我们所期望的步骤进行:
① 引入aop schema  在beans标签中添加:

xmlns:aop="http://www.springframework.org/schema/aop"

② 声明一个request作用域的bean,并在bean中创建代理

<bean name="xxx" class="xxx.xxx" scope="request"><aop:scoped-proxy/>
</bean>

③ 引用request作用域的bean:

<bean id="x" class="x.x"><property name="xxx" ref="xxx" />
</bean>

在上述例子中一个singleton作用域的bean引用了一个request作用域的bean。为了singleton的作用域的bean能获取到request作用域的bean,需要使用Spring AOP的语法为request作用域的bean配置一个代理类,为了能够在配置文件中使用AOP的配置标签,则需要在beans中声明中定义aop命名空间。
当singleton作用域的Bean在Web环境下调用request作用域的Bean时,Spring AOP将启动动态代理判断当前Bean位于哪个HTTP请求线程中,并从对应的HTTP请求线程域中获取对应的request作用域的Bean。
反过来说,在配置文件中添加<aop:scoped-proxy/>后,注入的Bean已经不是在配置文件中声明的Bean对象了,而是通过动态代理获取的Bean的实例。
Spring在动态代理类中加入一段逻辑,以判断当前的request作用域的Bean需要取得那个HTTP请求相关的Bean,首先判断当前request作用域的Bean在哪个线程中,然后根据这个线程获取对应的HttpRequest对象,在使用HttpRequest域中获取对应的request作用域的bean。因为Web容器的特性,一般情况下,一个HTTP请求对应一个独立的线程。
Java语言只能对接口提供自动代理,所以,如果需要对类提供代理,则需要在类路径中加入CGLib的类库,这时Spring将使用CGLib为类生成动态代理的子类。

spring:Bean作用域相关推荐

  1. spring bean作用域_Spring面试知识点,这是我见过最全面的 - 知识铺

    知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累.不占太多时间,不停地来唤醒记忆深处的知识点. Q1.什么是Spring框架? Spring是最流行的企业应用程序框架之一.Spring ...

  2. Spring Bean作用域实例

    在Spring中,bean作用域用于确定哪种类型的 bean 实例应该从Spring容器中返回给调用者.bean支持的5种范围域: 单例 - 每个Spring IoC 容器返回一个bean实例 原型- ...

  3. Struts2 Action 与Spring bean 作用域

    struts2 的action 是没有scope的,但通过引用spring bean 可以达到有scope功能. <action name="xxxAction" class ...

  4. spring bean作用域_Srping中Bean的三种装配方式:大魏Java记10

    一.Bean的作用域 Spring在初始化一个Bean实例时,可以同时为其指定特定的作用域.作用域将会对Bean的生命周期和创建方式产生影响. Bean的作用域类型: Singleton作用域是Spr ...

  5. Spring Bean 作用域之间的区别?

    Spring 容器中的bean 可以分为5 个范围.所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下: 1.singleton:这种bean 范围是默认的,这种范围确保不管接受到多少 ...

  6. Spring Bean作用域与生命周期

    目录 Bean的作用域: Bean有六大行为模式 1.singleton:单例模式(默认) 2.prototype: 原型模式(多例模式) 3.request: 请求作用域(Spring MVC) 4 ...

  7. ​Spring IOC中 Bean 作用域

    ​Spring Bean 作用域 Spring 3 中为Bean定义了5种作用域,它们是:singleton(单例).prototype(原型).request.session 和 global se ...

  8. Spring bean相关

    Spring中指定Bean的作用于的方式 以下四种为例: 单例(默认,可以不用特殊表明) @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) ...

  9. Spring的作用域与生命周期

    文章目录 一.lombok的安装与使用 二.Spring作用域 二.Bean原理分析 执行流程 Bean的生命周期 一.lombok的安装与使用 lombok插件可以提供给我们一些注释,这些注释可以很 ...

最新文章

  1. 2019-4-23 plan
  2. ios点击大头针气泡不弹出_地图大头针气泡点击事件
  3. Java API —— Map接口
  4. Matlab向量与多项式
  5. 程序员啊程序员...济南昊锐科技
  6. Loader 知识梳理(2) initLoader和restartLoader的区别
  7. Mybatis学习笔记-CURD(基于配置文件的方式)
  8. php 查询 判断 语句,关于php的判断语句
  9. [bzoj2932][POI1999]树的染色问题
  10. 分布式智能微电网的体系结构操作系统
  11. mysql 快速还原数据库_快速入门:备份和还原MySQL数据库的简便方法
  12. 常用的富文本编辑器插件
  13. 电子词典系统vc++_《VC++ 编程词典(珍藏版)》
  14. 选择 Mac 的 15 个充分理由
  15. 语音动画设置 android,Anroid Studio第七期 - 语音动画
  16. 【狂神说:秦疆】SpringMVC笔记
  17. 安全浏览器无法安装?看这一篇就够了
  18. potplayer快捷键
  19. GIS十问之一:到底什么单位招聘GIS专业的学生?
  20. 集合的运算(C++单链表实现)

热门文章

  1. 水仙花数是指一个三位数,它的每个位上的数字的 3次幂之和等于它本身,请编程找出所有水仙花数。(例如:153 = 1^3 + 5^3 + 3^3 )
  2. 【Java】数组:动态初始化 、静态初始化
  3. JS代码清除localStorage缓存
  4. CPC (Contrastive Predictive Coding)
  5. cpc按点击计算怎么算_什么是CPC(每次点击费用)?
  6. Linux中一些有用而炫酷的代码
  7. -- str --() 方法
  8. react svg 实现体温单 三测单
  9. mybatis技术全攻略指南
  10. vs2010打包系统必备选择.net framework 3.5sp1编译错误的解决方法