Spring中Bean的作用域深入剖析与技术实践
前言
Spring框架作为Java企业级应用开发中的中流砥柱,提供了强大的依赖注入(DI)和面向切面编程(AOP)等功能。在Spring框架中,Bean的作用域(Scope)是一个非常重要的概念,它决定了Bean实例的生命周期和共享方式。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring中Bean的作用域,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
一、Bean作用域概述
在Spring框架中,Bean的作用域决定了Bean实例在Spring IoC容器中的创建方式、生命周期以及共享方式。Spring支持多种作用域,每种作用域都有其特定的应用场景和生命周期管理策略。
1.1 作用域类型
Spring支持以下五种作用域:
- singleton:默认作用域,Spring IoC容器中仅存在一个Bean实例,所有对该Bean的请求都将返回同一个实例。
- prototype:每次请求Bean时都会创建一个新的实例,适用于有状态的Bean或需要频繁创建新实例的场景。
- request:每次HTTP请求都会创建一个新的Bean实例,仅在当前HTTP请求内有效,适用于Web应用程序。
- session:每次HTTP会话都会创建一个新的Bean实例,仅在当前HTTP会话内有效,适用于Web应用程序。
- globalSession:类似于session作用域,但仅在Portlet应用程序中使用,用于跨Portlet的会话共享。
1.2 作用域的选择原则
在选择Bean的作用域时,需要考虑以下几个因素:
- 性能:singleton作用域可以减少对象创建的开销,但需要注意线程安全问题;prototype作用域则每次都会创建新实例,可能导致性能下降。
- 状态管理:无状态的Bean适合使用singleton作用域,而有状态的Bean则应该使用prototype作用域或其他请求/会话作用域。
- 应用场景:根据Bean的具体应用场景选择合适的作用域,例如Web应用程序中常用request和session作用域来管理用户的会话状态。
二、Bean作用域的功能点
2.1 Singleton作用域
Singleton作用域是Spring的默认作用域,它保证了在整个应用程序中只有一个Bean实例。这种作用域适用于无状态的Bean,如服务类、工具类等。由于只有一个实例,因此需要注意线程安全问题。
示例代码
java复制代码
@Service
public class MyService {
// 业务逻辑代码
}
在上面的示例中,MyService
类被标记为@Service
,Spring会自动将其注册为singleton作用域的Bean。
2.2 Prototype作用域
Prototype作用域每次请求都会创建一个新的Bean实例。这种作用域适用于有状态的Bean或需要频繁创建新实例的场景。
示例代码
java复制代码
@Component
@Scope("prototype")
public class MyPrototypeBean {
// 有状态的属性
private String state;
public void setState(String state) {
this.state = state;}
public String getState() {
return state;}
}
在上面的示例中,MyPrototypeBean
类被标记为@Component
和@Scope("prototype")
,表示每次请求都会创建一个新的实例。
2.3 Request作用域
Request作用域每次HTTP请求都会创建一个新的Bean实例,仅在当前HTTP请求内有效。这种作用域适用于Web应用程序中需要管理用户请求状态的场景。
示例代码
java复制代码
@Component
@Scope("request")
public class MyRequestBean {
// 请求相关的属性
private String requestData;
public void setRequestData(String requestData) {
this.requestData = requestData;}
public String getRequestData() {
return requestData;}
}
在上面的示例中,MyRequestBean
类被标记为@Component
和@Scope("request")
,表示每次HTTP请求都会创建一个新的实例。
2.4 Session作用域
Session作用域每次HTTP会话都会创建一个新的Bean实例,仅在当前HTTP会话内有效。这种作用域适用于Web应用程序中需要管理用户会话状态的场景。
示例代码
java复制代码
@Component
@Scope("session")
public class MySessionBean {
// 会话相关的属性
private String sessionData;
public void setSessionData(String sessionData) {
this.sessionData = sessionData;}
public String getSessionData() {
return sessionData;}
}
在上面的示例中,MySessionBean
类被标记为@Component
和@Scope("session")
,表示每次HTTP会话都会创建一个新的实例。
2.5 GlobalSession作用域
GlobalSession作用域类似于session作用域,但仅在Portlet应用程序中使用,用于跨Portlet的会话共享。由于Portlet应用相对较少,因此这种作用域的使用场景也比较有限。
三、Bean作用域的背景
3.1 Spring框架的发展
Spring框架自2002年发布以来,经历了多个版本的迭代和更新。随着Java EE技术的发展和Web应用程序的普及,Spring框架逐渐成为了Java企业级应用开发的首选框架之一。在这个过程中,Bean作用域的概念也逐渐丰富和完善,以适应不同应用场景的需求。
3.2 Web应用程序的需求
在Web应用程序中,用户的状态管理是一个非常重要的问题。为了解决这个问题,Spring框架引入了request和session作用域,使得开发者可以方便地在Web应用程序中管理用户的请求状态和会话状态。随着Web技术的发展和Portlet应用的出现,Spring框架又引入了globalSession作用域来支持跨Portlet的会话共享。
四、Bean作用域的业务点
4.1 数据共享与隔离
不同的作用域决定了Bean实例的共享方式和生命周期。例如,singleton作用域的Bean在整个应用程序中只有一个实例,适用于全局共享的数据;而prototype作用域的Bean每次请求都会创建一个新的实例,适用于需要隔离数据的场景。在Web应用程序中,request和session作用域的Bean则分别用于管理请求级别和会话级别的数据。
4.2 性能优化
Bean作用域的选择对应用程序的性能有很大影响。例如,singleton作用域的Bean可以减少对象创建的开销,提高应用程序的性能;而prototype作用域的Bean则每次请求都会创建新实例,可能导致性能下降。因此,在选择Bean作用域时需要根据具体应用场景进行权衡和优化。
4.3 线程安全
对于singleton作用域的Bean来说,由于整个应用程序中只有一个实例,因此需要注意线程安全问题。如果Bean中存在可变的成员变量并且多个线程同时访问这些变量,就可能导致数据不一致或线程安全问题。为了避免这种问题,可以通过减少可变状态、使用不可变对象或同步代码块等方式来保证线程安全。
五、Bean作用域的底层原理
5.1 Bean的创建过程
在Spring框架中,Bean的创建过程可以分为以下几个步骤:
- 解析配置:Spring容器在启动时会解析配置文件或注解,获取Bean的定义信息。
- 实例化Bean:根据Bean的定义信息创建Bean的实例。对于singleton作用域的Bean来说,容器会在启动时就创建实例;而对于prototype作用域的Bean来说,则会在每次请求时创建实例。
- 设置属性:将Bean的依赖注入到其属性中。
- 初始化Bean:调用Bean的初始化方法(如果有的话)。
5.2 Bean的存储与获取
在Spring框架中,Bean实例被存储在IoC容器中。对于singleton作用域的Bean来说,容器会将其存储在一个单例缓存中;而对于prototype作用域的Bean来说,则不会存储在缓存中,每次请求时都会重新创建实例。当需要获取Bean实例时,容器会根据Bean的作用域从相应的存储位置中获取实例。
5.3 Bean的生命周期管理
不同的作用域决定了Bean实例的生命周期管理方式。对于singleton作用域的Bean来说,其生命周期与Spring容器相同,容器启动时创建实例,容器关闭时销毁实例;而对于prototype作用域的Bean来说,其生命周期则由开发者自行管理,每次请求时创建实例,使用完毕后由开发者负责销毁实例(实际上在Java中由垃圾回收器负责销毁)。对于request和session作用域的Bean来说,其生命周期则分别与HTTP请求和HTTP会话的生命周期相同。
六、实践案例与优缺点分析
6.1 实践案例一:单例Bean的管理
场景描述
在一个在线商城系统中,有一个商品服务类ProductService
用于处理商品的增删改查操作。由于商品服务类的实例在整个应用程序中只需要一个即可满足需求,因此可以选择将其配置为singleton作用域的Bean。
实现代码
java复制代码
@Service
public class ProductService {
// 商品服务相关的业务逻辑代码
}
在上面的代码中,ProductService
类被标记为@Service
,Spring会自动将其注册为singleton作用域的Bean。
优缺点分析
优点:
- 性能高:由于整个应用程序中只有一个实例,减少了对象创建的开销。
- 状态共享:所有请求共享同一个实例,方便数据共享。
缺点:
- 线程安全问题:如果有多个线程同时访问该实例并修改其状态,可能会导致数据不一致或线程安全问题。
- 灵活性较低:所有请求都复用同一个实例,不适合需要独立实例的场景。
6.2 实践案例二:原型Bean的管理
场景描述
在一个在线支付系统中,每次用户发起支付请求时都需要创建一个新的支付订单对象PaymentOrder
。由于每个支付订单都是独立的且需要保持状态信息(如订单金额、支付状态等),因此可以选择将其配置为prototype作用域的Bean。
实现代码
java复制代码
@Component
@Scope("prototype")
public class PaymentOrder {
// 支付订单相关的属性
private double amount;
private String status;
// 省略getter和setter方法
}
在上面的代码中,PaymentOrder
类被标记为@Component
和@Scope("prototype")
,表示每次请求都会创建一个新的实例。
优缺点分析
优点:
- 线程安全:每次请求都会创建一个新的实例,避免了多线程间的数据竞争问题。
- 灵活性高:适合需要独立实例或有状态Bean的场景。
缺点:
- 性能开销:频繁创建和销毁实例可能导致性能下降。
- 生命周期管理:需要开发者手动管理Bean的创建和销毁(实际上在Java中由垃圾回收器负责销毁),增加了编程复杂度。
6.3 实践案例三:请求作用域Bean的管理
场景描述
在一个Web应用程序中,需要记录用户的登录信息以便在请求处理过程中使用。由于登录信息只需要在当前HTTP请求内有效,因此可以选择将其配置为request作用域的Bean。
实现代码
java复制代码
@Component
@Scope("request")
public class UserLoginInfo {
// 用户登录信息相关的属性
private String username;
private String sessionId;
// 省略getter和setter方法
}
在上面的代码中,UserLoginInfo
类被标记为@Component
和@Scope("request")
,表示每次HTTP请求都会创建一个新的实例。
优缺点分析
优点:
- 线程安全:每个HTTP请求都会创建一个新的实例,天然地隔离了请求之间的状态。
- 资源节约:请求结束后自动销毁实例,避免了不必要的资源占用。
缺点:
- 适用范围限制:仅适用于Web应用程序且需要特定的Servlet容器支持。
- 生命周期短:仅在请求生命周期内有效,对于跨请求的数据管理不适用。
6.4 实践案例四:会话作用域Bean的管理
场景描述
在一个购物车系统中,需要记录用户的购物车信息以便在用户会话期间内持续有效。由于购物车信息需要在整个HTTP会话期间内有效且需要保持状态信息(如商品列表、总价等),因此可以选择将其配置为session作用域的Bean。
实现代码
java复制代码
@Component
@Scope("session")
public class ShoppingCart {
// 购物车相关的属性
private List<Product> products = new ArrayList<>();
private double totalPrice;
// 省略getter和setter方法以及业务逻辑代码
}
在上面的代码中,ShoppingCart
类被标记为@Component
和@Scope("session")
,表示每个HTTP会话都会创建一个新的实例。
优缺点分析
优点:
- 持久化会话状态:每个用户会话创建一个实例,可以用来保存会话级别的数据。
- 线程安全:每个用户拥有独立的实例避免了并发冲突。
缺点:
- 资源消耗:长时间的会话可能导致内存占用增加。
- 适用范围限制:同样局限于Web应用且依赖于会话管理机制。
七、总结与展望
通过本文的深入剖析和技术实践展示,我们可以对Spring中Bean的作用域有一个全新的认识。不同的作用域决定了Bean实例的创建方式、生命周期以及共享方式,对于优化应用性能、管理资源和确保线程安全至关重要。在未来的发展中,随着Java EE技术和Web应用程序的不断演进,Spring框架中的Bean作用域概念也将继续丰富和完善以适应更多应用场景的需求。作为开发者我们需要不断学习和掌握这些新技术以提升自己的竞争力并为企业创造更大的价值。
相关文章:
Spring中Bean的作用域深入剖析与技术实践
前言 Spring框架作为Java企业级应用开发中的中流砥柱,提供了强大的依赖注入(DI)和面向切面编程(AOP)等功能。在Spring框架中,Bean的作用域(Scope)是一个非常重要的概念,…...
Python爬虫实战:抓取拼多多商品详情数据(基于pdd.item_get接口)
在当前的电商市场中,拼多多以其独特的拼团模式和优惠价格吸引了大量用户,成为继淘宝、京东之后的又一大电商平台。对于数据分析和市场研究者来说,获取拼多多的商品详情数据显得尤为重要。本文将介绍如何使用Python爬虫技术,通过调…...
工具类-列表请求工具 useList
useList 用于列表请求的基于 vue 3 的 hooks,接收请求函数、请求参数等数据,自动生成请求请求函数,分页信息等 本文有涉及到 http 请求工具和接口返回格式的内容: http 工具:一个基于 axios 封装的请求工具Response…...
Scala中的正则表达式01
规则类型具体规则示例说明单字符大多数字符匹配自身正则表达式 abc,文本 abca 匹配 a,b 匹配 b,c 匹配 c方括号 [ ][ ] 定义字符集,匹配其一[abc],文本 a、b 或 c[abc] 匹配 a、b 或者 c排除字符集 [^ ][^ ] 开头加 ^&…...

基于SpringBoot的养老院管理系统的设计与实现
一、前言 随着人口老龄化的加剧,养老院作为老年人养老的重要场所,其管理的高效性和科学性显得尤为重要。传统的养老院管理方式多依赖人工操作,存在信息记录不及时、不准确,管理流程繁琐,资源调配困难等问题。利用信息技…...
Ansible变量详解(变量定义+变量优先级+变量注册+层级定义变量+facts缓存变量)
本篇文章详细给大家介绍Ansible变量,变量适合管理剧本中每个项目的动态值,或是某些值在多个地方重复使用,如果将此值设置为变量再在其他地方调用会方便许多。会用变量,才算真正会用Ansible,话不多说,直接开…...
面向对象系统的分析和设计
来源:《设计模式精解-GOF23种设计模式解析》 作者:k_eckel k_eckels mindview - 博客园 (cnblogs.com) --------- 面向对象系统的分析和设计实际上追求的就是两点: (1)高内聚 (2)低耦合 …...

Vue 提供了Transition,可以帮助你制作基于状态变化的过渡和动画
官方文档:https://cn.vuejs.org/guide/built-ins/transition.html Transition Vue 提供了两个内置组件,可以帮助你制作基于状态变化的过渡和动画: <Transition> 会在一个元素或组件进入和离开 DOM 时应用动画。本章节会介绍如何使用…...

视频编辑技术:一键生成混剪视频的AI技术应用
随着视频内容的爆炸式增长,视频编辑技术也在不断进步。本文将探讨如何利用AI技术,实现一键生成混剪视频,并自动添加配音和字幕,以提高视频编辑的效率和质量。 AI技术在视频编辑中的应用 AI技术在视频编辑领域的应用越来越广泛&am…...
Android11 MTK 开机默认启动热点
1、需求:开机后不锁屏,默认打开热点,且长时间没有设备连接热点时保证热点也是打开的。 2、开机后不锁屏: 路径:vendor/mediatek/proprietary/packages/apps/SettingsProvider/res/values/defaults.xml<bool name&q…...

Vue Web开发(二)
1. 项目搭建 1.1. 首页架子搭建 使用Element ui中的Container布局容器,选择倒数第二个样式,将代码复制到Home.vue。 1.1.1.下载less (1)下载less样式 npm i less (2)下载less编辑解析器 npm i less…...

Linux-实用操作
文章目录 一. 各类实用小技巧(快捷键)1. ctrl c 强制停止2. ctrl d 退出登出3. history 查看历史命令4. !命令前缀,自动匹配上一个命令5. ctrl r,搜索历史命令6. ctrl a | e,光标移动到命令开始或结束7. ctrl ← | →,左右跳…...

Elasticsearch:使用 Elastic APM 监控 Android 应用程序
一、前言 人们通过私人和专业的移动应用程序在智能手机上处理越来越多的事情。 拥有成千上万甚至数百万的用户,确保出色的性能和可靠性是移动应用程序和相关后端服务的提供商和运营商面临的主要挑战。 了解移动应用程序的行为、崩溃的发生和类型、响应时间慢的根本…...
Go的简单问题问答
基础问题回答 Go 的主要特点是什么? 简洁:语法简化,减少复杂性。并发:内置 Goroutine 和 Channel,支持轻量级并发。静态类型:强类型语言,编译时检查错误。跨平台:编译生成独立的二进…...

【攻防实验】溯源与取证分析实验
溯源与取证分析实验 溯源取证分析作为网络攻防过程中重要环节,准确找到攻击者的入侵线索(尤其是攻击突破口、攻击IP地址、域名、工具等信息),对于企业或者团队安全运营团队来说都是必备技能。常规攻击取证过程中往往会结合流量、Web访问日志、终端系统或…...
THREE.js 入门(一)xyz坐标系
一、坐标系概念 在 three.js 中,相机的默认朝向是沿着 Z 轴的负方向。也就是说,默认情况下,相机会沿着 Z 轴的负方向“看”到场景中的对象,而 X 轴和 Y 轴分别对应水平方向和垂直方向。换句话说,相机的默认位置是 (0,…...

AUTOSAR CP中基于通信模块(COM)的Transformer-R24的规范导读
该文档是关于 AUTOSAR CP中基于通信模块(COM)的Transformer的规范说明,主要内容包括引言、相关文档、约束与假设、功能规范、API 规范、配置规范等,旨在为汽车电子系统开发中基于 COM 的Transformer提供全面的技术规范和指导。 一…...
ubuntu20.04安装anygrasp_sdk
ubuntu20.04安装anygrasp_sdk采坑记录 安装ME的教程看上一篇,现在来看anygrasp安装问题grasp_detection、grasp_trackinglicense申请demo文件的运行注意的地方到这以为大功告成了,然后出现了一个numpy版本不匹配问题最后还有一个问题就是修改demo.sh,不然没法可视化结果展示安…...

Spring完整知识点二
Spring注解开发 Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,它能够代替xml配置文件,可以简化配置,提高开发效率Spring注解根据出现时间分类 Spring原始注解…...
GESP三级集训——课堂笔记(部分)
进制转换(二进制、十进制、八进制、十六进制等) 十进制(逢十进一)——Decimal 十进制是我们生活中最常见的进制,如“1”“23”“891”等: 进位过程如下:{1,2,3,4,5,6,7,8,9}{10,11,12,13,14,…...

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

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...