所有分类
  • 所有分类
  • 未分类

Spring–Bean的作用域(scope)–使用/详解

简介

本文介绍Spring(SpringBoot)的作用域(scope)及其用法。

作用域类型

Spring容器最初提供了两种bean的scope类型:singleton和prototype。Spring2.0以后,又引入了另外四种scope类型:request、session、application和global session,这三种只能在web 应用中才可以使用。

作用域类型适用范围描述
singleton所有Spring应用        Spring的默认scope。         在Spring的IoC容器中只存在一个对象实例,所有该对象的引用都共享这个实例。         一般情况下,无状态的bean使用该scope。
prototype所有Spring应用        每次对该bean的请求都会创建一个新的实例。         一般情况下,有状态的bean使用该scope。
requestSpring Web应用        每次http请求将会有各自的bean实例,类似于prototype。
sessionSpring Web应用        每个http session对应一个bean实例。
applicationSpring Web应用        Web工程生命周期。
global sessionSpring Web应用        global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。如果在非 portlet 环境将视为 session 作用域。         实践中基本用不到。

使用场景

scope类型什么时候声明为singleton,何时声明为prototype?

无状态的bean使用该scope。有状态的bean使用prototype。有状态和无状态会话bean的本质区别是它们的生命周期。

  • 有状态:bean保持了用户的信息,即“有状态”。
  • 无状态 :bean一旦实例化就被加进会话池中,各个用户都可以共用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

说明

在ssh2 项目中 , struts2的action交由spring管理的时候 ,spring默认是singleton的 ,而struts2的action显然是有状态的 ,所以必须显示设置为 scope=“prototype”;但是对那些Dao的实现类推介scope=“singleton” ,因为这些类没有状态,用singleton只需维护一个实例,显然性能高一些。

比较

用singleton 的性能要高一些 ,因为只有一个实例;

实际应用举例

之前在开发过程中遇到了一个问题,当request发起下一个请求的时候,action中的属性值并没有清除,而是继续采用上次使用过的参数值进行查询并响应,导致数据查询不真实或失败。对此,在spring配置文件的bean中添加属性scope=prototype即可。

详解

singleton

当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把 一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都 将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中 只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时 候,spring的IOC容器中只会存在一个该bean。

配置实例:

@Scope("singleton")

或者

@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)

prototype

prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。

不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。 清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用 bean的后置处理器,该处理器持有要被清除的bean的引用。)

配置实例:

<bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/>

或者

@Scope(“prototype”)

或者

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

request

request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。

@Scope(WebApplicationContext.SCOPE_REQUEST)

session

session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效,配置实例:配置实例:和request配置实例的前提一样,配置好web启动文件就可以如下配置:

@Scope(WebApplicationContext.SCOPE_SESSION)

application

application作用域表示该针对整个web项目生命周期:

@Scope(WebApplicationContext.SCOPE_APPLICATION)

global session

global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个 portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。如果你在web中使用global session作用域来标识bean,那么web会自动当成session类型来使用。配置实例:和request配置实例的前提一样,配置好web启动文件就可以如下配置:

@Scope(WebApplicationContext.SCOPE_APPLICATION)
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录