Spring 的Controller 是单例or多例

      你什么也不肯放弃,又得到了什么?

背景:今天写代码遇到一个Controller 中的线程安全问题,那么Spring 的Controller 是单例还是多例的呢?若为单例又如何保证并发安全呢?

一、面试回答

Spring管理的Controller,即加入@Controller 注入的类,默认是单例的,因此建议:

1、不要在Controller 中定义成员变量;(单例非线程安全,会导致属性重复使用)

2、若必须要在Controller 中定义一个非静态成员变量,则通过注解@Scope("prototype"),将其设置为多例模式。

二、验证Controller 单例

验证代码:

 package com.ausclouds.bdbsec.tjt;

 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @author tjt
* @time 2020-08-25
* @desc 验证Controller 单例
*/
@Controller
@ResponseBody
@RequestMapping("/tjt")
public class TestSingleController { private long money = 10; @GetMapping("/test1")
public long testSingleOne(){
money = ++money;
System.out.println("/tjt/test1: the money I have: " + money);
return money;
} @GetMapping("test2")
public long testSingleTwo(){
money = ++money;
System.out.println("/tjt/test2: the money I have: " + money);
return money;
} }

-拍一拍

首先,访问 http://localhost:8088/test1,得到的答案是11

接着,再访问 http://localhost:8088/test2,得到的答案是 12

不难看出:同一个变量,两次访问得到不同的结果,很明显是线程不安全的。

验证截图:

 三、Controller 如何实现多例?

尽量不要在Controller 中定义成员变量,若必须要在Controller 中定义一个非静态成员变量,则通过注解@Scope("prototype"),将其设置为多例模式;或者是在Controller 中使用ThreadLocal 变量。

验证代码:

 package com.ausclouds.bdbsec.tjt;

 import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @author tjt
* @time 2020-08-25
* @desc 验证Controller 单例
*/
@Controller
@ResponseBody
@Scope("prototype") // 将Controller 设置为多例模式
@RequestMapping("/tjt")
public class TestSingleController { private long money = 10; @GetMapping("/test1")
public long testSingleOne(){
money = ++money;
System.out.println("/tjt/test1: after use @Scope the money I have: " + money);
return money;
} @GetMapping("test2")
public long testSingleTwo(){
money = ++money;
System.out.println("/tjt/test2: after use @Scope the money I have: " + money);
return money;
} }

-拍一拍

在加上@Scope("prototype")后首先,访问 http://localhost:8088/test1,得到的答案是11

接着,再访问 http://localhost:8088/test2,得到的答案也是 11

不难看出:同一个变量,两次访问得到相同的结果。

验证截图:

四、作用域

其实,spring bean 的作用域除了上面使用的prototype 外,还有singleton、request、session 和global session 四种;其中request、session 和global session 主要运用在Web 项目中。

  • singleton:单例模式,当spring 创建applicationContext 容器的时候,spring会预初始化所有的该作用域实例,加上lazy-init 就可以避免预处理;
  • prototype:原型模式,每次通过getBean 获取该bean 就会新产生一个实例,创建后spring 将不再对其管理;
  • request:每次请求都新产生一个实例,和prototype 不同就是创建后,接下来的管理,spring依然在监听;
  • session:每次会话,同上;
  • global session:全局的web 域,类似于servlet 中的application。

你什么也不肯放弃,又得到了什么?

Spring 的Controller 是单例or多例的更多相关文章

  1. springboot默认创建的bean是单实还是多例

    转:https://blog.csdn.net/q1512451239/article/details/53122687 springboot默认创建的bean是单实还是多例 曾经面试的时候有面试官问 ...

  2. 转:【Spring MVC Controller单例陷阱】

    http://lavasoft.blog.51cto.com/62575/1394669/ Spring MVC Controller默认是单例的: 单例的原因有二:1.为了性能.2.不需要多例. 1 ...

  3. Spring MVC Controller单例陷阱

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://lavasoft.blog.51cto.com/62575/1394669 Spr ...

  4. spring的controller默认是单例还是多例

    转: spring的controller默认是单例还是多例 先看看spring的bean作用域有几种,分别有啥不同. spring bean作用域有以下5个: singleton:单例模式,当spri ...

  5. Spring5源码解析-Spring框架中的单例和原型bean

    Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...

  6. SpringMVC中的Controller默认单例

    众所周知,Servlet是单例的. 在struts中,Action是多例的,每一个请求都会new出来一个action来处理. 在Spring中,Controller默认是单例的,多个请求都会访问同一个 ...

  7. Spring对象类型——单例和多例

    由于看淘淘商城的项目,涉及到了项目中处理spring中bean对象的两种类型,分别是单例和多例,就在此记录一下,方便加深理解,写出更加健壮的代码. 一.单例和多例的概述 在Spring中,bean可以 ...

  8. Spring容器-ApplicationContext的单例设计

    Spring容器-ApplicationContext的单例设计   每次通过new创建一个ApplicationContext容器,都会执行refresh方法,看源代码了解到这个refresh方法会 ...

  9. SSM-Spring-05:Spring的bean是单例还是多例,怎么改变?

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- Spring的bean是单例的 它在Spring容器初始化的时候创建对象 可以修改为多例,在此bean节点中添 ...

随机推荐

  1. 安装fiddler 谷歌插件

    移动 .crx 插件无法安装问题 解决方案: 修改后缀名为 .zip 文件 进行解压后,使用浏览器扩展程序加载已解压的文件进行扩展 添加插件 2020-06-20

  2. == 和 is 的区别

    import copy a = ['a','b','c'] b = a #b和a引用自同一块地址空间 print("a==b :",a==b) print("a is b ...

  3. PHP is_array() 函数

    is_array() 函数用于检测变量是否是一个数组.高佣联盟 www.cgewang.com PHP 版本要求:PHP 4, PHP 5, PHP 7 语法 bool is_array ( mixe ...

  4. PHP lcfirst() 函数

    实例 把 "Hello" 的首字符转换为小写.: <?php高佣联盟 www.cgewang.comecho lcfirst("Hello world!" ...

  5. Spring进阶案例之注解和IoC案例

    Spring进阶案例之注解和IoC案例 一.常见的注解分类及其作用 从此前的基于xml的IoC开发案例和依赖注入案例中,我们可以将xml配置归纳为: <bean id="" ...

  6. easyui 属性 事件 方法

    在easyui当中 属性和事件可以按照json定义的对象来使用. /*在easyui中 属性和事件的使用方法相同*/ var loginWinJson = { closed: false, closa ...

  7. 学Java必看!零基础小白再也不用退缩了

    程序员们!请往这儿看 对于JAVA的学习,可能你还会有许多的顾虑 不要担心 接着往下看吧 学Java前 一.数学差,英语也不好是不是学不好Java? 答案是:是~ 因为你在问这个问题的时候说明你对自己 ...

  8. 一道 3 行代码的 Python面试题,我懵逼了一天

    有意思的题目 题目:写出下面程序运行结果 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的 ...

  9. Web For Pentester 学习笔记 - XSS篇

    XSS学习还是比较抽象,主要最近授权测的某基金里OA的XSS真的实在是太多了,感觉都可以做一个大合集了,加上最近看到大佬的博客,所以这里我也写一个简单的小靶场手册,顺带着也帮助自己把所有XSS的方式给 ...

  10. vue element Admin - 修改浏览器标签名 + 添加tagView标签 +固定导航头部 + 添加侧边栏Logo

    1 .修改浏览器标签名称: 修改浏览器标签名称在文件:\src\settings.js   image.png 2 .修改固定头部Header和侧边栏 Logo:   image.png 1)侧边栏文 ...