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. Django学习路37_request属性

      打印元信息,基本上都会打印出来 类字典结构的 key 键 允许重复   get 请求可以传参,但是长度有限制 最大不能超过 2K post 文件上传使用 get 参数 默认放在网址中 post 在 ...

  2. PHP xml_parse_into_struct() 函数

    定义和用法 xml_parse_into_struct() 函数把 XML 数据解析到数组中. 该函数把 XML 数据解析到 2 个数组中:高佣联盟 www.cgewang.com Value 数组 ...

  3. MySQL(版本8.0.19)服务的启动/停止、登录/登出、修改密码

      [先说明一点 ,windows系统下,英文字母不分大小写.] MySQL 服务的 启动 / 停止 方式一: (我的系统是windows10) 找到 此电脑 图标 右键点击,选择"管理&q ...

  4. MyBatis辟邪剑谱

    一 MyBatis简介 MyBatis是一个优秀的持久层框架 它对JDBC操作数据库的过程进行封装 开发者只需要关注SQL本身 而不需要花费精力去处理JDBC繁杂的过程代码 MyBatis将要执行的各 ...

  5. Selenium多窗口切换代码

    # #!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2020/7/31 16:05 # @Author : Gengwu # @FileNam ...

  6. fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题

    fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题

  7. 33-关键字:interface

    interface:接口 1.使用说明: * 1.接口使用interface来定义 * 2.Java中,接口和类是并列的两个结构 * 3.如何定义接口:定义接口中的成员 * 3.1 JDK7及以前:只 ...

  8. Chrome简洁高效管理下载项

    每次要查看下载记录时,Chrome新建下载标签页的速度能让我抓狂 之前用的 Chrono 界面太过传统,而且还不能点击打开.所以一直在寻找好用的下载管理插件,经过多次在拓展商城搜索比对,找到了这款拓展 ...

  9. 手把手教你使用Python网络爬虫获取招聘信息

    1.前言 现在在疫情阶段,想找一份不错的工作变得更为困难,很多人会选择去网上看招聘信息.可是招聘信息有一些是错综复杂的.而且不能把全部的信息全部罗列出来,以外卖的58招聘网站来看,资料整理的不清晰. ...

  10. java动态代理——代理方法的假设和验证及Proxy源码分析五

    前文地址 https://www.cnblogs.com/tera/p/13419025.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...