2019独角兽企业重金招聘Python工程师标准>>>

Scope作用域

在 Spring IoC 容器中具有以下几种作用域:

  • singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例,适用于无状态bean;
  • prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例,适用于有状态的Bean;
  • request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效;
  • session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效;
  • globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效。

@scope默认是单例模式(singleton),如果需要设置的话@scope("prototype")
或xml配置如下:

<bean id="service1" class="com.test.TestServiceImpl1" scope="singleton" />
<bean id="service2" class="com.test.TestServiceImpl2" scope="prototype" />

无状态会话bean

bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。
由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响。

有状态会话bean

每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。

有状态bean,如果配置为singleton,会出现线程安全问题

示例:

package com.test;
public class TestServiceImpl implements TestService{  private User user;public void test1(User u) throws Exception {  this.user = u;                          //1  test2();  }  public void test2() throws Exception {  System.out.println(user.getId());       //2 }
}

如果该Bean配置为singleton,在并发访问下会出现问题
假设有2个用户user1,user2访问,都调用到了该Bean。
1.当user1 调用到程序中的1步骤的时候,该Bean的私有变量user被付值为user1;
2.理想的状况,当user1走到2步骤的时候,私有变量user应该为user1;
3.但如果在user1调用到2步骤之前,user2开始运行到了1步骤了,由于单态的资源共享,则私有变量user被修改为user2;
4.这种情况下,user1的步骤2用到的user.getId()实际用到是user2的对象。
实际应该是这个例子不应该用实例变量,这样就使得这个Bean由无状态变成了有状态Bean。

常用web架构,线程安全问题场景分析

1.SSH架构系统

对于SSH架构的系统,很少关心这方面,因为我们用到的一般都是singleton. Bean的注入由Spring管理。

Struts2中的Action因为会有User这样的实例对象,是有状态信息的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。

Struts1是基于单例模式实现,也就是只有一个Action实例供多线程使用。默认的模式是前台页面数据通过actionForm传入,在action中的excute方法接收,这样action是无状态的,所以一般情况下Strunts1是线程安全的。如果Action中用了实例变量,那么就变成有状态了,同样是非线程安全的。像下面这样就是线程不安全的。

/** * 非线程安全的Struts1示例  *  */
public class UserAction extends Action {  // 因为Struts1是单例实现,有状态情况下,对象引用是非线程安全的  private User user;  public void execute() {  // do something...  }  public User getUser() {  return user;  }  public void setUser(User user) {  this.user = user;  }
}

2.Servlet

Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web 容器负责的。
一个Servlet类在Application中只有一个实例存在,有多个线程在使用这个实例。这是单例模式的应用。
无状态的单例是线程安全的,但我们如果在Servlet里用了实例变量(私有变量),那么就变成有状态了,是非线程安全的。
如下面的用法就是不安全的,因为user是有状态信息的。

public class UserServlet HttpServlet{     private User user;   public void doGet (HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{  //do something...  }
}

总结

  • singleton会造成资源混乱问题,而如果是prototype的话,就不会出现资源共享的问题。(即不会出现线程安全的问题)
  • 应该尽量使用无状态Bean.如果在程序中出现私有变量(该bean会变为有状态的,一旦在其他线程中发生改变,就会产生线程不安全),解决方案就是尽量替换为方法中的参数。对于每个访问私有变量的方法增加变量传入(参数传入)或者通过ThreadLocal来获取。
  • 如果用有状态的bean,就要用prototype模式,每次在注入的时候就重新创建一个bean,在多线程中互不影响。
  • 如Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是相当于不变(immutable)类,所以不影响。
  • Stateless无状态用单例Singleton模式,Stateful有状态就用原型Prototype模式。

转载于:https://my.oschina.net/xhx6616/blog/1536592

spring bean scope作用域及多线程安全问题场景分析相关推荐

  1. spring bean的作用域和生命周期

    一.spring bean的作用域 五种作用域:singleton.prototype.request.session.globalSession request.session和global ses ...

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

    Bean的作用域 在bean声明时它有一个scope属性,它是用于描述bean的作用域. 可取值有: singleton:单例 代表在spring ioc容器中只有一个Bean实例 (默认的scope ...

  3. Spring -Bean的作用域

    在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域. 默认情况下 bean 是单例的 但有的时候, bean 就不能使单例的. 例如: Str ...

  4. Spring Bean的作用域(作用范围)

    文章目录 scope 1. 注解方式配置1.1 测试singleton1.2 测试prototype 2. XML方式配置 在Spring中使用 scope来表示一个bean定义对应产生实例的类型,也 ...

  5. 说说 Spring Bean 的作用域

    配置文件中定义 Bean 时,我们不但可以配置 Bean 的属性值以及相互之间的依赖关系,还可以定义 Bean 的作用域 .作用域会对 Bean 的生命周期和创建方式产生影响 . Bean 的作用域类 ...

  6. spring Bean的作用域(注解 单例 多例)

    通过@Scope注解,指定Bean的作用域(默认是 singleton 单例) 回顾:XML的方式<bean id="" class="" scope=& ...

  7. Spring bean - scope详解

    ​ Scope是定义Spring如何创建bean的实例的. 在创建bean的时候可以带上scope属性,scope有下面几种类型. Singleton 这也是Spring默认的scope,表示Spri ...

  8. Spring Bean的作用域之prototype

    Spring中Bean的默认最用域是单例,即singleton prototype是只在每次getBean的时候都去重新创建一个对象.下面我们来掩饰一下这种场景 使用SpringBoot项目.创建两个 ...

  9. Spring Bean Scope 有状态的Bean 无状态的Bean

    在Spring的Bean配置中,存在这样两种情况: [xhtml] view plaincopy <bean id="testManager" class="com ...

最新文章

  1. 处理错误:ORA-27101: shared memory realm does not exist 解决方案
  2. python 实现语音转文字_python3实现语音转文字(语音识别)和文字转语音(语音合成)...
  3. 天天红单app下载安装_App内测好帮手,稳定内测分发就选择TF签名
  4. NFT平台Polkamon将于3月31日在Polkastarter进行IDO
  5. 高阶函数-sort()与sorted() (三分钟读懂)
  6. Codeforces123E. Maze【树形dp】【概率dp】【证明题】
  7. python中创建二维列表
  8. 【ansible/ansible-tower】
  9. 阿里云 HotFix 注意事项
  10. 真人拳皇项目第二次Scrum总结——史经浩
  11. 创业起步 中小型网吧的组建解决方案(转)
  12. 所有人望向黑洞那一刻,我们短暂地共享了 5500 万光年外的世界
  13. Android高版本上传图片出现旋转问题(三星手机,小米8)
  14. 学编程和学机器人有什么区别
  15. Unity Shader入门精要第四章:学习Shader 所需的数学基础--坐标空间
  16. html状态中的302代码含义,网站状态码301与302的作用与区别
  17. redis 健康检查
  18. Matlab的护眼模式设置
  19. 新浪微博因“明星势力榜”投诉问题被约谈
  20. vue 文本显示组件_一个Vue组件,可在您键入时突出显示文本

热门文章

  1. 可测试性如何帮助团队提升效率
  2. Android 访问WebService
  3. Nginx虚拟机主机根据不同的域名使用不同的root路径
  4. Nginx相关基础配置详解
  5. LAMP编译安装之———httpd
  6. mongodb常用管理命令
  7. Bootloader
  8. “艾妮”(ANI)蠕虫病毒
  9. 安装Autodesk Vault Server 总提示需要重启计算机?
  10. linux下vi命令大全[转]