spring中的scope对线程安全问题影响(并发情况下scope设置
不⽤属性值注意事项)
Scope描述的是Spring容器如何新建Bean实例的。Spring的Scope有以下⼏种,通过@Scope注解来实现。
(1)Singleton:⼀个Spring容器中只有⼀个Bean的实例,此为Spring的默认配置,全容器共享⼀个实例。
(2)Prototype:每次调⽤新建⼀个Bean实例。
(3)Request:Web项⽬中,给每⼀个 http request 新建⼀个Bean实例。
(4)Session:Web项⽬中,给每⼀个 http session 新建⼀个Bean实例。
(5)GlobalSession:这个只在portal应⽤中有⽤,给每⼀个 global http session 新建⼀个Bean实例。
spring的controller、service、dao都是默认singleton的,在singleton的模式下spring只会⽣成⼀个对象来处理并发的请求并发导致结果与期望不符案例 :
1. scope概论
spring中scope是⼀个⾮常关键的概念,简单说就是对象在spring容器(IOC容器)中的⽣命周期,也可以理解为对象在spring容器中的创建⽅式。
2. scope历史及分类
⽬前,scope的取值有5种取值:
在Spring 2.0之前,有singleton和prototype两种;
在Spring 2.0之后,为⽀持web应⽤的ApplicationContext,增强另外三种:request,session和global session类型,它们只实⽤于web程序,通常是和XmlWebApplicationContext共同使⽤。
3.单个scope详解
1)singleton (单⼀实例)
此取值时表明容器中创建时只存在⼀个实例,所有引⽤此bean都是单⼀实例。如同每个国家都有⼀个总统,国家的所有⼈共⽤此总统,⽽这个国家就是⼀个spring容器,总统就是spring创建的类的bean,国家中的⼈就是其它调⽤者,总统是⼀个表明其在spring中的scope为singleton,也就是单例模型。
此外,singleton类型的bean定义从容器启动到第⼀次被请求⽽实例化开始,只要容器不销毁或退出,该类型的bean的单⼀实例就会⼀直存活,典型单例模式,如同servlet在web容器中的⽣命周期。
单例情况下:  不能使⽤共享成员变量  ,  在并发情况下本来是true , 但另⼀线程进来 , 变为false ,  期望结果是true , 并发会导致数据不准确
session和application的区别
2)prototype
请求⽅spring容器在进⾏输出prototype的bean对象时,会每次都重新⽣成⼀个新的对象给,虽然这种类型的对象的实例化以及属性设置等⼯作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求⽅之后,容器就不在拥有当前对象的引⽤,请求⽅需要⾃⼰负责当前对象后继⽣命周期的管理⼯作,包括该对象的销毁。也就是说,容器每次返回请求⽅该对象的⼀个新的实例之后,就由这个对
象“⾃⽣⾃灭”,最典型的体现就是spring与struts2进⾏整合时,要把action的scope改为prototype。
属性值为prototype时 , 并发时线程是安全的
如同分苹果,将苹果的bean的scope属性声明为prototype,在每个⼈领取苹果的时候,我们都是发⼀个新的苹果给他,发完之后,别⼈爱怎么吃就怎么吃,爱什么时候吃什么时候吃,但是注意吃完要把苹果核扔到垃圾箱!对于那些不能共享使⽤的对象类型,应该将其定义的scope设为prototype。
3)request
再次说明request,session和global session类型只实⽤于web程序,通常是和XmlWebApplicationContext共同使⽤。
<bean id ="requestPrecessor" class="...RequestPrecessor"  scope="request" />
Spring容器,即XmlWebApplicationContext 会为每个HTTP请求创建⼀个全新的RequestPrecessor对象,当请求结束后,该对象的⽣命周期即告结束,如同java web中request的⽣命周期。当同时有100个HTTP请求进来的时候,容器会分别针对这10个请求创建10个全新的RequestPrecessor实例,且他们相互之间互不⼲扰,简单来讲,request可以看做prototype的⼀种特例,除了场景更加具体之外,语意上差不多。
4)session
对于web应⽤来说,放到session中最普遍的就是⽤户的登录信息,对于这种放到session中的信息,我们可以使⽤如下形式的制定scope 为session:
<bean id ="userPreferences" class="...UserPreferences"  scope="session" />
Spring容器会为每个独⽴的session创建属于⾃⼰的全新的UserPreferences实例,⽐request scope的bean会存活更长的时间,其他的⽅⾯没区别,如果java web中session的⽣命周期。
5)global session
<bean id ="userPreferences" class="...UserPreferences"  scope="globalsession" />
global session只有应⽤在基于porlet的web应⽤程序中才有意义,它映射到porlet的global范围的session,如果普通的servlet的web 应⽤中使⽤了这个scope,容器会把它作为普通的session的scope对待。
4.scope配置
1)xml⽅式
进⾏bean的配置时,指定scope。
2)注解⽅式
前提为配置spring为注解配置。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。