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)能够识别时间意…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...



