Spring 懒加载的实际应用
引言
在 Spring 框架中,懒加载机制允许你在应用程序运行时延迟加载 Bean。这意味着 Bean 只会在第一次被请求时才实例化,而不是在应用程序启动时就立即创建。这种机制可以提高应用程序的启动速度,并节省内存资源。
Spring 的懒加载机制
- 懒加载属性:
- 在 Spring 中,可以通过在 Bean 定义中设置
lazy-init="true"属性来启用懒加载。这告诉 Spring 容器在启动时不要初始化该 Bean,而是在第一次请求时再初始化。 - 也可以通过
@Lazy注解在类级别启用懒加载。
- 在 Spring 中,可以通过在 Bean 定义中设置
- 懒加载的工作原理:
- 当 Spring 启动时,容器会读取配置文件或注解,并将 Bean 定义加载到容器中。
- 如果 Bean 被标记为懒加载,那么 Spring 不会立即实例化该 Bean。
- 当应用程序第一次尝试访问懒加载的 Bean 时,Spring 会检查容器中是否存在该 Bean 的实例。
- 如果不存在,Spring 会创建一个新的实例并将它放入容器中。
- 之后,所有的请求都将从容器中获取已存在的实例。
懒加载的适用场景
Spring 的懒加载机制是一种优化技术,它允许你在应用程序启动时不立即初始化某些 Bean,而是在第一次需要这些 Bean 时才进行初始化。这种机制可以带来几个好处,包括但不限于减少应用程序启动时间、降低内存占用以及提高系统的响应速度。
适用场景
- 大型应用程序:
- 在大型应用程序中,可能存在大量的 Bean,其中一些 Bean 可能在应用程序运行的大部分时间内都不会被使用。在这种情况下,懒加载可以避免这些 Bean 在启动时被加载,从而加快应用程序的启动速度。
- 内存敏感的应用程序:
- 对于内存敏感的应用程序,懒加载可以减少启动时的内存消耗,因为只有真正需要的 Bean 才会被加载到内存中。
- 按需加载的组件:
- 如果某些组件只在特定条件下才会被使用,那么可以将这些组件设置为懒加载。这样,除非确实需要,否则这些组件不会占用任何资源。
- 第三方库或服务:
- 如果应用程序集成了第三方库或服务,而这些库或服务在启动时会进行耗时的初始化工作,那么可以考虑将这些集成设置为懒加载。
- 性能优化:
- 对于性能要求较高的应用程序,懒加载可以帮助优化启动过程,减少不必要的初始化操作,从而提高系统响应速度。
解决的问题
- 减少启动时间:
- 通过延迟 Bean 的初始化,可以显著减少应用程序的启动时间。这对于需要快速启动的应用程序尤其重要。
- 降低内存占用:
- 懒加载可以避免一次性加载所有 Bean,从而减少应用程序的初始内存占用。这对于资源受限的环境特别有用。
- 提高性能:
- 减少启动时的初始化操作可以提高应用程序的整体性能,特别是在高负载环境下。
- 避免不必要的初始化:
- 对于那些在应用程序运行期间很少或几乎不被使用的 Bean,懒加载可以避免它们在启动时进行不必要的初始化。
- 简化部署:
- 懒加载可以简化部署过程,因为应用程序可以更快地启动并准备好接收请求。
如何启用懒加载
- 使用
@Lazy注解:- 在类级别添加
@Lazy注解,这会告诉 Spring 容器在首次请求该 Bean 时才初始化它。
- 在类级别添加
- XML 配置文件:
- 如果使用 XML 配置文件,可以为
<bean>元素添加lazy-init="true"属性来启用懒加载。
- 如果使用 XML 配置文件,可以为
- Java 配置:
- 在 Java 配置中,可以使用
@Bean方法上的@Lazy注解来启用懒加载。
- 在 Java 配置中,可以使用
示例代码
假设你有一个 LazyLoadedService 类,你希望它在第一次被请求时才初始化:
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Lazy;@Service
@Lazy
public class LazyLoadedService {public void doSomething() {System.out.println("LazyLoadedService is doing something...");}
}
在这个示例中,@Lazy 注解确保了 LazyLoadedService 只有在第一次被请求时才会被初始化。
循环依赖问题
懒加载还可以帮助解决某些类型的循环依赖问题,尤其是在 Spring 容器中。循环依赖是指两个或多个 Bean 互相依赖对方,这可能导致 Spring 在初始化这些 Bean 时出现问题。下面我将详细介绍懒加载如何帮助解决循环依赖问题,并提供一些具体的示例。
循环依赖发生在两个或多个 Bean 互相依赖的情况下。例如,假设你有两个 Bean,BeanA 和 BeanB,它们互相依赖对方:
@Service
public class BeanA {private final BeanB beanB;@Autowiredpublic BeanA(BeanB beanB) {this.beanB = beanB;}// ...
}@Service
public class BeanB {private final BeanA beanA;@Autowiredpublic BeanB(BeanA beanA) {this.beanA = beanA;}// ...
}
在 Spring 中,当容器试图初始化 BeanA 时,它需要先初始化 BeanB,而初始化 BeanB 又需要先初始化 BeanA。这导致了一个无限递归的问题。
解决方案
Spring 提供了几种机制来解决循环依赖问题:
- 使用
@Lazy注解:- 通过在至少一个 Bean 上使用
@Lazy注解,可以让 Spring 在第一次请求时才初始化这个 Bean。这可以打破循环依赖链。
- 通过在至少一个 Bean 上使用
- 利用 Spring 的代理机制(该机制在2.6.x版本之后被弃用了):
- Spring 容器可以为 Bean 创建一个代理,使得在初始化过程中可以使用代理对象而不是实际的对象。这样可以避免无限递归。
使用 @Lazy 解决循环依赖:
为了打破循环依赖,你可以将其中一个 Bean 设置为懒加载:
@Service
@Lazy
public class BeanA {private final BeanB beanB;@Autowiredpublic BeanA(BeanB beanB) {this.beanB = beanB;}// ...
}@Service
public class BeanB {private final BeanA beanA;@Autowiredpublic BeanB(BeanA beanA) {this.beanA = beanA;}// ...
}
在这个例子中,BeanA 被标记为懒加载。这意味着当 Spring 初始化 BeanB 时,它不需要立即初始化 BeanA。当第一次请求 BeanA 时,Spring 才会真正初始化它。这有效地打破了循环依赖。
Spring 处理循环依赖的代理机制:
Spring 容器在处理循环依赖时,会根据依赖的类型来决定如何解决。以下是三种不同类型的循环依赖及其处理方式:
- 构造函数注入循环依赖:
- 如果循环依赖是通过构造函数注入发生的,Spring 会使用部分构造好的对象(即尚未完全初始化的对象)来解决循环依赖。这意味着 Spring 会在构造函数注入过程中传递一个代理对象,而不是完整的 Bean 实例。
- setter 方法注入循环依赖:
- 如果循环依赖是通过 setter 方法注入发生的,Spring 会在构造完成后立刻注入代理对象,而不是完整的 Bean 实例。
- 字段注入循环依赖:
- 如果循环依赖是通过字段注入发生的,Spring 会采用与 setter 方法注入类似的方法,即在构造完成后立即注入代理对象。
在这个例子中,BeanA 和 BeanB 彼此依赖对方。Spring 会自动处理这种循环依赖,具体步骤如下:
- 初始化
BeanA:- Spring 开始初始化
BeanA,但在构造函数中需要BeanB。 - Spring 创建一个
BeanB的代理对象,并将其传递给BeanA的构造函数。
- Spring 开始初始化
- 初始化
BeanB:- Spring 开始初始化
BeanB,但在构造函数中需要BeanA。 - Spring 创建一个
BeanA的代理对象,并将其传递给BeanB的构造函数。
- Spring 开始初始化
- 完成初始化:
- 一旦
BeanA和BeanB都构造完成,Spring 会使用这些代理对象来完成它们的初始化。
- 一旦
代理对象的使用:
代理对象在初始化阶段充当实际 Bean 的占位符。这意味着 BeanA 和 BeanB 在构造时实际上持有的是代理对象,而不是实际的 Bean 实例。当这些 Bean 被真正使用时,Spring 会使用实际的 Bean 实例替换代理对象。
注意事项
- 代理机制:
- 即使使用了懒加载,Spring 仍可能为 Bean 创建代理对象来解决循环依赖问题。这意味着即使
BeanA是懒加载的,BeanB仍然可以持有指向BeanA的代理对象。
- 即使使用了懒加载,Spring 仍可能为 Bean 创建代理对象来解决循环依赖问题。这意味着即使
- 性能影响:
- 懒加载可能会稍微增加第一次请求懒加载 Bean 时的延迟,因为此时需要初始化该 Bean。
- 设计模式:
- 如果循环依赖是由于设计不当造成的,考虑重构代码以避免这种依赖关系。例如,可以使用策略模式、观察者模式等设计模式来重新组织代码。
总结
懒加载机制是一种有用的优化手段,它可以帮助提高应用程序的性能和响应能力。通过合理地使用懒加载,你可以确保应用程序在启动时只加载必要的组件,从而提高整体性能。
相关文章:
Spring 懒加载的实际应用
引言 在 Spring 框架中,懒加载机制允许你在应用程序运行时延迟加载 Bean。这意味着 Bean 只会在第一次被请求时才实例化,而不是在应用程序启动时就立即创建。这种机制可以提高应用程序的启动速度,并节省内存资源。 Spring 的懒加载机制 懒…...
PyQT 串口改动每次点开时更新串口信息
class MainWindow(QWidget, Ui_Form):def __init__(self):super().__init__(parentNone)self.setupUi(self)self.comboBox.installEventFilter(self) # 加载事件过滤器self.comboBox.addItems(get_ports())def eventFilter(self, obj, event): # 定义事件过滤器if isinstance(o…...
三级_网络技术_19_路由器的配置及使用
1.在Cisco路由器上配置DHCP服务,使得客户端可以分配到的地址范围是222.28.71.2-222.28.71.200地址租用时间是2小时30分钟,不记录地址冲突日志默认路由是222.28.71.1,分配的dns服务器地址是222.28126.27和222.28.126.26。以下配置完全正确的是…...
【STM32 Blue Pill编程】-STM32CubeIDE开发环境搭建与点亮LED
开发环境搭建与点亮LED 文章目录 开发环境搭建与点亮LED1、STM32F103C8T6及STM32 Blue Pill 介绍2、下载并安装STM32CubeIDE3、编程并点亮LED3.1 在Stm32CubeIDE中编写第一个STM32程序3.1.1 创建项目3.1.2 设备配置3.1.2.1 系统时钟配置3.1.2.2 系统调试配置3.1.2.3 GPIO配置3.…...
【数据结构】六、图:4.图的遍历(深度优先算法DFS、广度优先算法BFS)
三、基本操作 文章目录 三、基本操作1.图的遍历1.1 深度优先遍历DFS1.1.1 DFS算法1.1.2 DFS算法的性能分析1.1.3 深度优先的生成树和生成森林 1.2 广度优先遍历BFS1.2.1 BFS算法1.2.2 BFS算法性能分析1.2.3 广度优先的生成树和生成森林 1.3 图的遍历与图的连通性 1.图的遍历 图…...
29、号外!号外!ERA5再分析数据下载方式更新啦
文章目录 1. 前言2. 账号注册与协议签署2.1 账号注册2.2 签署CDS-Beta使用条款2.3 更新.cdsapi文件 3. 常见问题与解决方法(持续更新中)3.1 问题1:更新完.cdsapi文件之后,原有下载代码不可以使用3.2 问题2: RuntimeError: 403 Cli…...
智能识别,2024年SD卡数据恢复软件的智能进化
除了手机之外现在有不少的设备还是依靠SD卡来存储数据,比如相机、摄像头、无人机等。有的时候会因为一些意外的情况导致数据丢失,那是真的丢失了吗?大部分情况还是可以依靠sd卡数据恢复工具来找回这些“消失”的数据哦。 1.福昕数据恢复 链…...
浙大数据结构慕课课后题(04-树5 Root of AVL Tree)
题目要求: AVL 树是一种自平衡的二叉搜索树。在 AVL 树中,任何节点的两个子子树的高度最多相差一;如果在任何时候它们相差不止一,则进行重新平衡以恢复此属性。图 1-4 说明了旋转规则。 图1 图2 图3 图4 现在给定一系列插入,您应该…...
Golang | Leetcode Golang题解之第331题验证二叉树的前序序列化
题目: 题解: func isValidSerialization(preorder string) bool {n : len(preorder)slots : 1for i : 0; i < n; {if slots 0 {return false}if preorder[i] , {i} else if preorder[i] # {slots--i} else {// 读一个数字for i < n &&…...
zdppy+vue3+onlyoffice文档管理系统项目实战 20240812上课笔记
遗留问题 1、增加新建和导入按钮,有按钮了,但是还没有完善,图标还不对,需要解决 2、登录功能 3、用户管理 4、角色管理 5、权限管理 6、分享功能 解决新建和导入的图标问题 解决代码: <a-button type"prim…...
怎么将mov视频转换成mp4?将mov视频转换成mp4的方法
怎么将mov视频转换成mp4?由于mov格式通常与苹果设备兼容性较好,而mp4则更广泛地支持于各种播放器和设备中,因此将mov转换为mp4可以确保视频在更多场景下能够流畅播放。通过这种转换,你可以确保视频在各种平台和设备上的兼容性&…...
大数据技术——实战项目:广告数仓(第五部分)
目录 第9章 广告数仓DIM层 9.1 广告信息维度表 9.2 平台信息维度表 9.3 数据装载脚本 第10章 广告数仓DWD层 10.1 广告事件事实表 10.1.1 建表语句 10.1.2 数据装载 10.1.2.1 初步解析日志 10.1.2.2 解析IP和UA 10.1.2.3 标注无效流量 10.2 数据装载脚本 第9章 广…...
计算机毕业设计 家电销售展示平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
C# 根据MySQL数据库中数据,批量删除OSS上的垃圾文件
protected void btndeleteTask_Click(object sender, EventArgs e){//获取标识为已删除数据,一次加载500条int countlocks _goodsItemsApplication.CountAllNeedExecuteTask();int totalPagelocks (countlocks 500 - 1) / 500;//分批次处理for (int curentpage …...
Vue3+Element-plus+setup使用vuemap/vue-amap实现高德地图API相关操作
首先要下载依赖并且引入 npm安装 // 安装核心库 npm install vuemap/vue-amap --save// 安装loca库 npm install vuemap/vue-amap-loca --save// 安装扩展库 npm install vuemap/vue-amap-extra --save cdn <script src"https://cdn.jsdelivr.net/npm/vuemap/vue-a…...
Windows配置开机直达桌面并跳过锁屏登录界面在 Windows 10 中添加在启动时自动运行的应用
目录 Win10开机直达桌面并跳过锁屏登录界面修改组策略修改注册表跳过登录界面 在 Windows 10 中添加在启动时自动运行的应用设置系统级别服务一、Windows下使用sc将应用程序设置为系统服务1. 什么是sc命令?2. sc命令的基本语法3. 创建Windows服务的步骤与示例创建服…...
pythonUI自动化007::pytest的组成以及运行
pytest组成: 测试模块:以“test”开头或结尾的py文件 测试用例:在测试模块里或测试类里,名称符合test_xxx函数或者示例函数。 测试类:测试模块里面命名符合Test_xxx的类 函数级: import pytestclass Test…...
开放式耳机哪个品牌好用又实惠?五大口碑精品分享
如今开放式耳机市场日益火爆,不少知名品牌都在对产品进行升级迭代,那么如何在一众品牌型号中选择到自己最满意的那一款呢?开放式耳机哪个品牌好用又实惠?这就需要更专业的选购攻略,因此笔者专门整理出了专业机构的开放…...
代码随想录算法训练营day39||动态规划07:多重背包+打家劫舍
多重背包理论 描述: 有N种物品和一个容量为V 的背包。 第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。 求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。 本质: …...
WebSocket革新:用PHP实现实时Web通信
标题:WebSocket革新:用PHP实现实时Web通信 在现代Web应用中,实时通信是一个不可或缺的功能。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,它允许服务器主动向客户端推送数据,极大地简化了客户端和服务器之…...
JAVA重点基础、进阶知识及易错点总结(35)注解与反射
🚀 Java 巩固进阶 第 35 天 主题:注解与反射结合 —— 让注解"活"起来📅 进度概览:继昨天学习注解定义之后,今天进入 注解的核心应用场景:注解 反射。单独的注解只是"标签"ÿ…...
从选题到发布全托管:我用OpenClaw搭建了个人自媒体AI流水线
一、引言:内容创作者的普遍痛点 作为技术博主,相信很多人都遇到过这些问题: 选题焦虑:每天花1-2小时刷各大平台找热点,不知道写什么内容读者喜欢效率低下:写一篇技术文章需要查资料、写内容、排版、配图、同…...
预算有限AI率还有80%,性价比最高的降AI方案
AI率80%,但预算只有100-200元,怎么处理? 这是一个真实存在的困境。不同工具的定价差异很大,预算不够时怎么取舍,怎么用最少的钱解决问题? 这篇文章给出不同预算下的最优方案。 先了解各工具定价 工具定…...
Dual-Loop Adaptive AI System Whitepaper(DLAAS)双环自适应AI系统正式命名白皮书
Dual-Loop Adaptive AI System Whitepaper(DLAAS)双环自适应AI系统—— 基于六元结构(TSPR-WEB-LLM-HIC-A-F)的生成式AI决策操作系统版权与所有权声明本技术系统的全部知识产权归以下主体独家所有:拓世网络技术开发室&…...
Boss-Key老板键:一键隐藏窗口的终极隐私保护神器
Boss-Key老板键:一键隐藏窗口的终极隐私保护神器 【免费下载链接】Boss-Key 老板来了?快用Boss-Key老板键一键隐藏静音当前窗口!上班摸鱼必备神器 项目地址: https://gitcode.com/gh_mirrors/bo/Boss-Key 你是否曾经历过这样的尴尬时刻…...
数字游民装备:OpenClaw+Qwen3-32B的轻量化旅行方案
数字游民装备:OpenClawQwen3-32B的轻量化旅行方案 1. 为什么数字游民需要本地AI助手 去年在巴厘岛旅居时,我深刻体会到数字游民的工作痛点:不稳定的网络、时区差异导致的协作延迟、以及移动办公场景下的效率损耗。当你在咖啡馆处理文件时&a…...
OpenClaw与Python:构建高效自动化脚本,赋能复杂工作场景落地
OpenClaw与Python:构建高效自动化脚本,赋能复杂工作场景落地摘要在数字化转型浪潮席卷全球的今天,自动化技术已成为提升企业运营效率、降低人力成本、应对复杂业务挑战的关键利器。其中,机器人流程自动化(RPAÿ…...
家庭游戏服务器搭建指南:使用Sunshine打造跨设备游戏串流体验
家庭游戏服务器搭建指南:使用Sunshine打造跨设备游戏串流体验 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 在数字化时代,游戏玩家越来越需要灵活的游戏方…...
解放你的双手:OpenKore如何让RO游戏效率提升300%的实战指南
解放你的双手:OpenKore如何让RO游戏效率提升300%的实战指南 【免费下载链接】openkore A free/open source client and automation tool for Ragnarok Online 项目地址: https://gitcode.com/gh_mirrors/op/openkore 想象一下,当其他玩家还在手动…...
细节见真章:JamTools 聚合工具的用户体验设计与实践
在软件市场竞争日益激烈的今天,用户体验已经成为决定软件成败的关键因素之一。 一款软件,无论功能多么强大,如果用户体验不好,就很难获得用户的认可。 JamTools 作为一款免费开源的聚合工具软件,不仅在功能上满足了用户…...
