2023.11.11 关于 Spring 中 Bean 的作用域
目录
Bean 的作用域
作用域的定义
Singleton(单例作用域)
Prototype(原型作用域)
Request(请求作用域)
Session(会话请求)
Application(全局作用域)
WebSocket(WebSocket 会话作用域 )
设置 Bean 的作用域
@Scope 注解
使用方式建议
Bean 的作用域
作用域的定义
- 作用域(Scope)指变量、函数或对象在程序中可见和访问的范围
- Bean 的作用域 指 Bean 在 Spring 整个框架中的某种 行为模式
Bean 的 6 种作用域
- Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域
Singleton(单例作用域)
- 该作用域下的 Bean 在 Spring 容器中只存在一个实例:获取 Bean(即通过 context.getBean 等方法获取)及装配 Bean(通过 @Autowired 注入)都是同一个对象
- Spring 容器在第一次请求时创建该实例,并在后续请求中返回相同的实例
- 默认情况下,Spring 的 Bean 作用域为 Singleton
- 因为 单例模式 的性能更好
Prototype(原型作用域)
可理解为 多例作用域
每次请求获取 Bean 时,都会创建一个新的实例
每次获取 Bean 时都会返回一个新的对象,即原型作用域的 Bean 实例不会被共享
Request(请求作用域)
- 在 Web 应用程序中,每个 HTTP 请求将创建一个新的 Bean 实例,并且该实例仅在当前请求的范围内可见
- 对于每个请求,都会有一个单独的 Bean 实例
Session(会话请求)
- 在 Web 应用程序中,每个用户会话均会创建一个新的 Bean 实例,并且该实例仅在当前用户会话的范围内可见
- 对于每个用户会话,都会有一个单独的 Bean 实例
Application(全局作用域)
- 在 Web 应用程序中,整个应用程序范围内只会创建一个Bean 实例,并且该实例将被共享和重用
WebSocket(WebSocket 会话作用域 )
- 在基于 WebSocket 的应用程序中,每个 WebSocket 会话均会创建一个新的 Bean 实例,并且该实例仅在当前 WebSocket 会话的范围内可见
注意:
- 在普通的 Spring 项目中只有前两种作用域,即前两种为 Spring 核心作用域
- 后四种状态是 Spring MVC 中的作用域
建议阅读下文之前 点击下方链接了解 Lombok 的作用
Lombok 的作用和使用
实例理解
- 我们先创建一个实体类 User
import lombok.Data;@Data public class User {public int id;public String name; }
- 再创建一个 UserBean 类,用来向 Spring 容器中 存储 User 类型的 Bean 对象
- 此处向 Spring 容器中存入一个 id 为 user,且 name = 张三的 Bean 对象
import com.java.demo.enity.User; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component;@Component public class UserBeans {@Beanpublic User user() {User user = new User();user.setId(1);user.setName("张三");return user;} }
- 新创建 UserController 类
- 该类中新创建了一个 myUser 对象,且该对象赋值于注入进来的 user Bean 对象
- 并修改 myUser 对象的 name 属性
- 将从 user Bean 对象赋值而来的 name = 张三,修改为 name = 小林
import com.java.demo.enity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;@Controller public class UserController {@Autowiredprivate User user;public void printUser() {System.out.println("UserController 类注入的 user Bean 对象,也就是 user 变量的初始值 -> " + user.toString()); // 修改 UserUser myUser = user;myUser.setName("小林");System.out.println("UserController 类中的 myUser 对象 -> " + myUser.toString());System.out.println("UserController 类修改 myUser 对象 name 属性后再次打印 user 变量 -> " + user.toString());} }
- 新创建 UserController2 类
- 同样在该类中注入 user Bean 对象
import com.java.demo.enity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;@Controller public class UserController2 {@Autowiredprivate User user;public void printUser2() {System.out.println("UserController2 类注入的 user Bean 对象 -> " + user.toString());} }
- 最后再创建一个启动类
- 该类用来从 Spring 容器中拿 UserController 类和 UserController2 类的 Bean 对象,并调用它们的成员方法
import com.java.demo.controller.UserController; import com.java.demo.controller.UserController2; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");UserController userController = context.getBean("userController",UserController.class);userController.printUser();UserController2 userController2 = context.getBean("userController2",UserController2.class);userController2.printUser2();} }
运行结果:
- 该运行结果与我们的预期结果不同诶!
- 为啥 UserController2 类中从 Spring 容器中拿到的 user Bean 对象其 name = 小林 ?
原因解释:
- 正因为默认情况下,Spring 的 Bean 作用域为 Singleton,即 单例作用域
- 即存储在 Spring 容器中的 id = user 的 Bean 对象仅有一份
- 所以此处的 user 变量和 myUser 变量 均指向同一个对象(引用)
- 即 myUser 变量在对其 name 进行修改时
- 其他任何注入了 id = user 的 Bean 对象 的变量,也会跟着修改 name
设置 Bean 的作用域
@Scope 注解
- 我们可以通过 @Scope 注解来设置 Bean 对象的作用域
实例理解
- 如果我们不主动设置该 Bean 对象的作用域,其默认为 Singleton(单例作用域)
- 所以为了解决上述实例问题所产生的问题,我们可以将该 Bean 对象主动设置为 prototype(原型作用域),即多例模式
方式一:直接在 @Scope 注解中填入 prototype
import com.java.demo.enity.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component public class UserBeans {@Bean@Scope("prototype")public User user() {User user = new User();user.setId(1);user.setName("张三");return user;} }
方式二:使用 ConfigurableBeanFactory 接口中定义的常量 SCOPE_PROTOTYPE,该常量表示原型作用域
import com.java.demo.enity.User; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;@Component public class UserBeans {@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public User user() {User user = new User();user.setId(1);user.setName("张三");return user;} }
- 当我们修改完 Bean 对象的作用域时,再次运行启动类,观察运行结果
运行结果:
- UserController2 类中从 Spring 容器中拿到的 user Bean 对象其 name = 张三
- 也就是说,在 UserController 类中,进行的修改操作并未影响到 Spring 容器中的初始 Bean 对象
使用方式建议
- 上述两种方式起到的效果是相同的,但是推荐使用第二种方式
- 使用第一种 直接填入 prototype 方式的前提是 你能够清楚的记得该单词是如何拼写的
- 而第二种方式,IDEA 自带自动补全提示,可以保证我们不出错!
相关文章:

2023.11.11 关于 Spring 中 Bean 的作用域
目录 Bean 的作用域 作用域的定义 Singleton(单例作用域) Prototype(原型作用域) Request(请求作用域) Session(会话请求) Application(全局作用域) …...

5 Paimon数据湖之表数据查询详解
更多Paimon数据湖内容请关注:https://edu.51cto.com/course/35051.html 虽然前面我们已经讲过如何查询Paimon表中的数据了,但是有一些细节的东西还需要详细分析一下。 首先是针对Paimon中系统表的查询,例如snapshots\schemas\options等等这些…...

时间序列预测实战(十二)DLinear模型实现滚动长期预测并可视化预测结果
官方论文地址->官方论文地址 官方代码地址->官方代码地址 个人修改代码->个人修改的代码已经上传CSDN免费下载 一、本文介绍 本文给大家带来是DLinear模型,DLinear是一种用于时间序列预测(TSF)的简单架构,DLinear的核…...

封神教程:腾讯云3年轻量应用服务器老用户购买方法
腾讯云轻量应用服务器特价是有新用户限制的,所以阿腾云建议大家选择3年期轻量应用服务器,一劳永逸,免去续费困扰。腾讯云轻量应用服务器3年优惠可以选择2核2G4M和2核4G5M带宽,3年轻量2核2G4M服务器540元,2核4G5M轻量应…...
Ubuntu(WSL2) 安装最新版的 cmake
Ubuntu(WSL) 安装最新版的 cmake 具体流程如下: 步骤一:卸载原本的 cmake sudo apt-get remove cmake 步骤二: sudo apt-get update sudo apt-get install apt-transport-https ca-certificates gnupg software-properties-common wget 步…...
Android---内存泄漏的优化
内存泄漏是一个隐形炸弹,其本身并不会造成程序异常,但是随着量的增长会导致其他各种并发症:OOM,UI 卡顿等。 为什么要将 Activity 单独做预防? 因为 Activity 承担了与用户交互的职责,因此内部需要持有大…...
C/S架构学习之基于UDP的本地通信(客户机)
基于UDP的本地通信(客户机):创建流程:一、创建数据报式套接字(socket函数): int sock_fd socket(AF_UNIX,SOCK_DGRAM,0);if(-1 sock_fd){perror("socket error");exit(-1);}二、创建…...

【性能测试】服务端中间件docker常用命令解析整理(详细)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、搜索 docker …...

【探索Linux】—— 强大的命令行工具 P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)
阅读导航 引言一、进程间通信概念二、进程间通信目的三、进程间通信分类四、管道1. 什么是管道2. 匿名管道(1)创建和关闭⭕pipe() 函数⭕创建匿名管道⭕关闭匿名管道 (2)通信方式(3)用法示例(4&…...

图论12-无向带权图及实现
文章目录 带权图1.1带权图的实现1.2 完整代码 带权图 1.1带权图的实现 在无向无权图的基础上,增加边的权。 使用TreeMap存储边的权重。 遍历输入文件,创建TreeMap adj存储每个节点。每个输入的adj节点链接新的TreeMap,存储相邻的边和权重 …...
每日一题(LeetCode)----数组--有序数组的平方
每日一题(LeetCode)----数组–有序数组的平方 1.题目([977. 有序数组的平方](https://leetcode.cn/problems/sqrtx/)) 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。…...
SpringCloud微服务:Eureka
目录 提供者与消费者 服务调用关系 eureka的作用 在Eureka架构中,微服务角色有两类 Eureka服务 提供者与消费者 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)服务消费者:一次业务中,调用其它微服务的服务。(调…...

19.删除链表的倒数第N个结点(LeetCode)
想法一 先用tail指针找尾,计算出节点个数,再根据倒数第N个指定删除 想法二 根据进阶的要求,只能遍历一遍链表,那刚刚想法一就做不到 首先,我们要在一遍内找到倒数第N个节点,所以我们设置slow和fast两个指…...

PyTorch技术和深度学习——三、深度学习快速入门
文章目录 1.线性回归1)介绍2)加载自由泳冠军数据集3)从0开始实现线性回归模型4)使用自动求导训练线性回归模型5)使用优化器训练线性回归模型 2.使用torch.nn模块构建线性回归模型1)使用torch.nn.Linear训练…...
360导航恶意修改浏览器启动页!我的chrome和IE均中招,如何解决?
0,关闭360等“安全”软件 1,按下组合键winR 2,输入regedit,回车 3,按下组合键ctrlF 4,输入http://hao.360.cn,查找下一个 5,查到一个注册表键值就删一个,一个不放过…...

RabbitMQ的高级特性
目录 数据导入 MQ的常见问题 消息可靠性问题 生产者确认机制 SpringAMQP实现生产者确认 消息持久化 消费者消息确认 失败重试机制 消费者失败消息处理策略 死信交换机 TTL 延时队列 安装插件 SpringAMQP使用插件 消息堆积问题 惰性队列 MQ的高可用 普通集群 …...

Java自学第10课:JavaBean和servlet基础
目录 目录 1 JavaBean (1)概念 (2)分类 (3)使用 2 servlet (1)代码结构 (2)常用接口 (3)如何开发 1 新建servlet 2 配置 1…...
AR打卡小程序:构建智能办公的新可能
【内容摘要】 随着技术的飞速发展,智能办公已不再是遥不可及的梦想。在这其中,AR打卡小程序以其独特的技术优势,正逐步成为新型办公生态的重要组成部分。本文将探讨AR打卡小程序的设计理念、技术实现以及未来的应用前景,并尝试深…...

Python环境安装、Pycharm开发工具安装(IDE)
Python下载 Python官网 Python安装 Python安装成功 Pycharm集成开发工具下载(IDE) PC集成开发工具 Pycharm集成开发工具安装(IDE) 安装完成 添加环境变量(前面勾选了Path不用配置) (1&…...

报时机器人的rasa shell执行流程分析
本文以报时机器人为载体,介绍了报时机器人的对话能力范围、配置文件功能和训练和运行命令,重点介绍了rasa shell命令启动后的程序执行过程。 一.报时机器人项目结构 1.对话能力范围 (1)能够识别欢迎语意图(greet)和拜拜意图(goodbye) (2)能够识别时间意…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...