解决@Scope(“prototype“)不生效的问题
目录
- @Scope(“prototype“)不生效
- @Scope(“prototype“)正确用法——解决Bean多例问题
- 1.问题,Spring管理的某个Bean需要使用多例
- 2.问题升级
- 3. Spring给出的解决问题的办法(解决Bean链中某个Bean需要多例的问题)
@Scope(“prototype“)不生效
使用spring的时候,我们一般都是使用@Component实现bean的注入,这个时候我们的bean如果不指定@Scope,默认是单例模式,另外还有很多模式可用,用的最多的就是多例模式了,顾名思义就是每次使用都会创建一个新的对象,比较适用于写一些job,比如在多线程环境下可以使用全局变量之类的
创建一个测试任务,这里在网上看到大部分都是直接@Scope(“prototype”),这里测试是不生效的,再加上proxyMode才行,代码如下
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
测试
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
结果
没重复的值,说明多线程环境下,全局变量没有问题
@Scope(“prototype“)正确用法——解决Bean多例问题
1.问题,Spring管理的某个Bean需要使用多例
在使用了Spring的web工程中,除非特殊情况,我们都会选择使用Spring的IOC功能来管理Bean,而不是用到时去new一个。
Spring管理的Bean默认是单例的(即Spring创建好Bean,需要时就拿来用,而不是每次用到时都去new,又快性能又好),但有时候单例并不满足要求(比如Bean中不全是方法,有成员,使用单例会有线程安全问题,可以搜索线程安全与线程不安全的相关文章),你上网可以很容易找到解决办法,即使用@Scope("prototype")注解,可以通知Spring把被注解的Bean变成多例
如下所示:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
分别发送请求http://localhost:8043/testScope/aaa和http://localhost:8043/testScope/bbb,控制台输出:
34name:aaa
34name:aaa
35name:bbb
34name:bbb
(34和35是两个线程的ID,每次运行都可能不同,但是两个请求使用的线程的ID肯定不一样,可以用来区分两个请求。)可以看到第二个请求bbb开始后,将name的内容改为了“bbb”,第一个请求的name也从“aaa”改为了“bbb”。要想避免这种情况,可以使用@Scope("prototype"),注解加在TestScope这个类上。加完注解后重复上面的请求,发现第一个请求一直输出“aaa”,第二个请求一直输出“bbb”,成功。
2.问题升级
多个Bean的依赖链中,有一个需要多例
第一节中是一个很简单的情况,真实的Spring Web工程起码有Controller、Service、Dao三层,假如Controller层是单例,Service层需要多例,这时候应该怎么办呢?
2.1一次失败的尝试
首先我们想到的是在Service层加注解@Scope("prototype"),如下所示:
controller类代码
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Service类代码
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
分别发送请求http://localhost:8043/testScope/aaa和http://localhost:8043/testScope/bbb,控制台输出:
32name:aaa--order:aaa
32name:aaa--order:aaa
34name:bbb--order:bbb
32name:bbb--order:bbb
可以看到Controller的name和Service的orderNum都被第二个请求从“aaa”改成了“bbb”,Service并不是多例,失败。
2.2 一次成功的尝试
我们再次尝试,在Controller和Service都加上@Scope("prototype"),结果成功,这里不重复贴代码,读者可以自己试试。
2.3 成功的原因(对2.1、2.2的理解)
Spring定义了多种作用域,可以基于这些作用域创建bean,包括:
- 单例( Singleton):在整个应用中,只创建bean的一个实例。
- 原型( Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
对于以上说明,我们可以这样理解:虽然Service是多例的,但是Controller是单例的。如果给一个组件加上@Scope("prototype")注解,每次请求它的实例,spring的确会给返回一个新的。问题是这个多例对象Service是被单例对象Controller依赖的。而单例服务Controller初始化的时候,多例对象Service就已经注入了;当你去使用Controller的时候,Service也不会被再次创建了(注入时创建,而注入只有一次)。
2.4 另一种成功的尝试(基于2.3的猜想)
为了验证2.3的猜想,我们在Controller钟每次去请求获取Service实例,而不是使用@Autowired注入,代码如下:
Controller类
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
用于获取Spring管理的Bean的类
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
Order的代码不变。
分别发送请求http://localhost:8043/testScope/aaa和http://localhost:8043/testScope/bbb,控制台输出:
31name:aaa--order:aaa
33name:bbb--order:bbb
31name:bbb--order:aaa
33name:bbb--order:bbb
可以看到,第二次请求的不会改变第一次请求的name和orderNum。问题解决。我们在2.3节中给出的的理解是对的。
3. Spring给出的解决问题的办法(解决Bean链中某个Bean需要多例的问题)
虽然第二节解决了问题,但是有两个问题:
- 方法一,为了一个多例,让整个一串Bean失去了单例的优势;
- 方法二,破坏IOC注入的优美展现形式,和new一样不便于管理和修改。
Spring作为一个优秀的、用途广、发展时间长的框架,一定有成熟的解决办法。经过一番搜索,我们发现,注解@Scope("prototype")(这个注解实际上也可以写成@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,使用常量比手打字符串不容易出错)还有很多用法。
首先value就分为四类:
ConfigurableBeanFactory.SCOPE_PROTOTYPE
,即“prototype”ConfigurableBeanFactory.SCOPE_SINGLETON
,即“singleton”WebApplicationContext.SCOPE_REQUEST
,即“request”WebApplicationContext.SCOPE_SESSION
,即“session”
他们的含义是:
singleton
和prototype分别代表单例和多例;request
表示请求,即在一次http请求中,被注解的Bean都是同一个Bean,不同的请求是不同的Bean;session
表示会话,即在同一个会话中,被注解的Bean都是使用的同一个Bean,不同的会话使用不同的Bean。
使用session和request产生了一个新问题,生成controller的时候需要service作为controller的成员,但是service只在收到请求(可能是request也可能是session)时才会被实例化,controller拿不到service实例。为了解决这个问题,@Scope注解添加了一个proxyMode的属性,有两个值ScopedProxyMode.INTERFACES和ScopedProxyMode.TARGET_CLASS,前一个表示表示Service是一个接口,后一个表示Service是一个类。
相关文章:

解决@Scope(“prototype“)不生效的问题
目录 Scope(“prototype“)不生效Scope(“prototype“)正确用法——解决Bean多例问题 1.问题,Spring管理的某个Bean需要使用多例2.问题升级3. Spring给出的解决问题的办法(解决Bean链中某个Bean需要多例的问题) Scope(“prototype“)不生效 …...

Mybatis 知识点
Mybatis 知识点 1.1 Mybatis 简介 1.1.1 什么是 Mybatis Mybatis 是一款优秀的持久层框架支持定制化 SQL、存储过程及高级映射Mybatis 几乎避免了所有的 JDBC 代码和手动设置参数以及获取结果集MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO…...

PHP中关于is,between,in等运算符的用法是什么?
我们学习了解了这么多关于PHP的知识,不知道你们对PHP中关于is,between,in等运算符的用法是什么?是否已经完全掌握了呢,如果没有,那就跟随本篇文章一起继续学习吧 相关推荐:关于PHP中的增删改如…...

2023-07-29:华清远见嵌入式2017年线下班:文件IO笔记
这里写目录标题 华清远见嵌入式2017年线下班:文件IO笔记文件权限文件IO文件创建和打开操作文件关闭操作出错处理创建设备文件 || create || 老师自己忘了文件读操作练习:计算文件的大小?文件写操作练习:打开file1和file2ÿ…...

2023年第四届“华数杯”数学建模思路 - 复盘:光照强度计算的优化模型
文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米,宽为12米࿰…...

Typescript第七章 处理错误(返回null,抛出异常,返回异常,Option类型)
第七章 处理错误 Typescript竭尽所能,把运行时异常转移到编译时。Typescript是功能丰富的系统,加上强大的静态和符号分析能力,包揽了大量辛苦的工作。 但是有些问题是无法避免的,比如网络和文件系统异常,解析用户输入…...

Qt库xcb问题
首先在~/.bashrc中加入 export QT_DEBUG_PLUGINS1然后看具体的报错 查看某个库链接的库: ldd libqxcb.so然后找到真正缺少的库,再在路径下搜索,然后建立软链接。 https://blog.csdn.net/LOVEmy134611/article/details/107212845 https://…...

C++ | 哈希表的实现与unordered_set/unordered_map的封装
目录 前言 一、哈希 1、哈希的概念 2、哈希函数 (1)直接定址法 (2)除留余数法 (3)平方取中法(了解) (4)随机数法(了解) 3、哈…...

【漏洞挖掘】Xray+rad自动化批量漏洞挖掘
文章目录 前言一、挖掘方法二、使用步骤工具安装使用方法开始挖掘 总结 前言 自动化漏洞挖掘是指利用计算机程序和工具来扫描、分析和检测应用程序、网络和系统中的安全漏洞的过程。这种方法可以帮助安全专家和研究人员更高效地发现和修复潜在的安全威胁,从而提高整…...

Swagger UI教程 API 文档和Node的使用
在团队开发中,一个好的 API 文档可以减少很多交流成本,也可以使一个新人快速上手业务。 前言 swagger ui是一个API在线文档生成和测试的利器,目前发现最好用的。为什么好用?Demo 传送门 支持API自动生成同步的在线文档 这些文档可…...

P5691 [NOI2001] 方程的解数
[NOI2001] 方程的解数 题目描述 已知一个 n n n 元高次方程: ∑ i 1 n k i x i p i 0 \sum\limits_{i1}^n k_ix_i^{p_i} 0 i1∑nkixipi0 其中: x 1 , x 2 , … , x n x_1, x_2, \dots ,x_n x1,x2,…,xn 是未知数, k 1 ,…...

rust里用什么表示字节类型?
在Rust中,字节可以使用 u8 类型来表示。 u8 是一个无符号8位整数类型,可以表示0到255之间的值,对应于一个字节的范围。 以下是一个示例,演示了如何声明和使用字节: fn main() {let byte: u8 65; // 表示字母A的ASCI…...

CMake简介
文章目录 为什么需要头文件为什么 C 需要声明头文件 - 批量插入几行代码的硬核方式头文件进阶 - 递归地使用头文件 CMake什么是编译器多文件编译与链接CMake 的命令行调用为什么需要库(library)CMake 中的静态库与动态库CMake 中的子模块子模块的头文件如…...

[threejs]相机与坐标
搞清相机和坐标的关系在threejs初期很重要,否则有可能会出现写了代码,运行时一片漆黑的现象,这种情况就有可能是因为你相机没弄对。 先来看一下threejs中的坐标(世界坐标) 坐标轴好理解,大家只需要知道在three中不同颜色代表的轴…...

Qt信号与槽机制的基石-MOC详解
引入 上篇讲到了信号与槽就是实现的观察者模式,那具体如何生成映射表就是moc做的事情。 一、moc简介 1. moc的定义 moc 全称是 Meta-Object Compiler,也就是“元对象编译器”,它主要用于处理C源文件中的非标准C代码。Qt 程序在交由标准编…...

关于单体架构缓存刷新实现方案
背景 如果各位看官是分布式项目应该都采用分布式缓存了,例如redis等,分布式缓存不在本次讨论范围哈;我个人建议是,如果是用户量比较大,建议采用分布式缓存机制,后期可以很容易前后到分布式服务或微服务。 …...

洞悉安全现状,建设网络安全防护新体系
一、“网络攻防演练行动“介绍 国家在2016年发布《网络安全法》,出台网络安全攻防演练相关规定:关键信息基础设施的运营者应“制定网络安全事件应急预案,并定期进行演练”。同年“实战化网络攻防演练行动”成为惯例。由公安部牵头࿰…...

spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象
😀前言 本章是spring基于XML 配置bean系类中第4篇讲解spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象 🏠个人主页:尘觉主页 🧑个人简介:大家好,我是尘觉,希望…...

三元组表实现矩阵相加(数据结构)
代码: 含注释,供参考 #include <stdio.h> #include <stdlib.h>typedef struct {int row,col,value;//分别为行数,列数,数值 } Triple; typedef struct {int len;//非零数值的个数Triple data[200]; } TSMatrix;void…...

ChinaJoy 2023微星雷鸟17游戏本震撼发布:搭载AMD锐龙9 7945HX首发8499元
ChinaJoy 2023展会中微星笔记本再次给大家带来惊喜,发布了搭载AMD移动端16大核的旗舰游戏本:雷鸟17,更重要的这样一款旗舰性能的游戏本,首发价8499元堪称当今游戏本市场中的“性价比爆款”! 本着和玩家一同制霸游戏战场…...

各种运算符
算术运算符 1.双目运算符 */%:从左到右优先级依次降低 一些注意事项: 1若a/b都为整型那么结果也为整型,如果ab其中有一个为实型,结果则为实型 求余运算符注意事项: 1运算对象必须为整数 2运算结果的整数跟左边数字的…...

yolov3-tiny原理解析及代码分析
前言 从去年十一月份开始学习yolo神经网络用于目标识别的硬件实现,到现在已经六个月了。一个硬件工程师,C/C基础都差劲的很,对照着darknet作者的源码和网上东拼西凑的原理讲解,一点一点地摸索。刚开始进度很慢,每天都…...

深入了解Redis-实战篇-短信登录
深入了解Redis-实战篇-短信登录 一、故事背景二、知识点主要构成2.1、短信登录2.1.1、生成随机短信验证码引入maven依赖生成验证码 2.1.2、实现登录校验拦截器2.1.3、基于Redis实现短信登录2.1.3.1、发送验证码时存入Redis2.1.3.2、登录时校验验证码 2.1.4、解决状态登录刷新的…...

Mysql的锁
加锁的目的 对数据加锁是为了解决事务的隔离性问题,让事务之前相互不影响,每个事务进行操作的时候都必须先加上一把锁,防止其他事务同时操作数据。 事务的属性 (ACID) 原子性 一致性 隔离性 持久性 事务的隔离级别 锁…...

【EI/SCOPUS征稿】2023年算法、图像处理与机器视觉国际学术会议(AIPMV2023)
2023年算法、图像处理与机器视觉国际学术会议(AIPMV2023) 2023 International Conference on Algorithm, Image Processing and Machine Vision(AIPMV2023) 2023年算法、图像处理与机器视觉国际学术会议(AIPMV2023&am…...

Go语言性能优化建议与pprof性能调优详解——结合博客项目实战
文章目录 性能优化建议Benchmark的使用slice优化预分配内存大内存未释放 map优化字符串处理优化结构体优化atomic包小结 pprof性能调优采集性能数据服务型应用go tool pprof命令项目调优分析修改main.go安装go-wrk命令行交互界面图形化火焰图 性能优化建议 简介: …...

K阶斐波那契数列(数据结构)
代码: 注意k阶斐波那契序列定义:第k和k1项为1,前k - 1项为0,从k项之后每一项都是前k项的和 例如:k2时,斐波那契序列为:0,1,1,2,3,5,8,13... k3时,斐波那契序列为:0,0,…...

【JavaEE】博客系统前后端交互
目录 一、准备工作 二、数据库的表设计 三、封装JDBC数据库操作 1、创建数据表对应的实体类 2、封装增删改查操作 四、前后端交互逻辑的实现 1、博客列表页 1.1、展示博客列表 1.2、博客详情页 1.3、登录页面 1.4、强制要求用户登录,检查用户的登录状态 …...

Redis 简介
文章目录 Redis 简介 Redis 简介 Redis(Remote Dictionary Server),远程词典服务器,基于 C/S 架构,是一个基于内存的键值型 NoSQL 数据库,开源,遵守 BSD 协议,Redis 由 C语言 实现。…...

CS162 13-17 虚拟内存
起源 为啥我们需要虚拟内存-----------需求是啥? 可以给程序提供一个统一的视图,比如多个程序运行同一个代码段的话,同一个kernel,就可以直接共享 cpu眼里的虚拟内存 无限内存的假象 设计迭代过程 为啥这样设计? 一…...