Spring缓存深入解析:@Cacheable的使用详解
摘要:在本文中,我们将深入研究Spring框架中的
@Cacheable
注解。我们会通过详细的Java示例,探讨如何使用这个功能强大的注解来提升应用程序性能。
一、什么是缓存?
在计算机科学中,缓存是一种存储技术,用于保存经常使用的数据,以便在后续请求中快速访问。在Web开发中,缓存被广泛用于减少对数据库的访问,提高应用程序的响应速度。
二、Spring中的缓存抽象
Spring提供了一种强大的缓存抽象,允许开发者通过简单的注解,将方法的执行结果存储在缓存中。这些注解包括@Cacheable
、@CacheEvict
、@CachePut
等。在本文中,我们将重点关注@Cacheable
注解。
三、@Cacheable注解的使用
@Cacheable
注解用于标记应该被缓存的方法。当一个方法被@Cacheable
注解标记后,Spring会在调用该方法前检查缓存,如果缓存中存在对应的数据,就直接返回缓存的数据,而不执行方法。如果缓存中不存在对应的数据,Spring会执行方法,然后将返回结果存入缓存。
@Cacheable
注解有两个重要的属性:value
和key
。value
用于指定缓存的名称,key
用于指定缓存的键。例如:
@Cacheable(value = "users", key = "#id")
public User findUserById(Long id) {//...
}
在上述代码中,findUserById
方法的结果将被存储在名为users
的缓存中,缓存的键是方法的参数id
。
四、@Cacheable注解的工作原理
让我们通过一个例子来详细了解@Cacheable
注解的工作原理。
假设我们有一个UserService
类,该类有一个findUserById
方法,用于从数据库中查询用户。我们可以使用@Cacheable
注解来缓存查询结果,如下:
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Cacheable(value = "users", key = "#id")public User findUserById(Long id) {return userRepository.findById(id).orElse(null);}
}
当我们第一次调用findUserById
方法时,Spring会执行方法,并将返回结果存入名为users
的缓存中。缓存的键是方法的参数id
。
当我们再次以相同的id
调用findUserById
方法时,Spring会在users
缓存中查找键为id
的数据。如果找到,直接返回缓存的数据,不执行方法。如果没找到,执行方法,并将返回结果存入缓存。
这就是@Cacheable
注解的工作原理。通过使用@Cacheable
注解,我们可以避免重复的数据库查询,提高应用程序的响应速度。
五、示例
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);//template.setKeySerializer(new StringRedisSerializer());//template.setValueSerializer(new GenericJackson2JsonRedisSerializer());FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);template.setValueSerializer(fastJsonRedisSerializer);template.setHashValueSerializer(fastJsonRedisSerializer);// 设置键(key)的序列化采用StringRedisSerializer。template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());return template;}@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory factory) {return RedisCacheManager.create(factory);}
}
@Cacheable(value = "queryAllBill", key = "#billRequestDto.userId + '_' + (#billRequestDto.billStatusList != null ? #billRequestDto.billStatusList.toString() : '') " +" + '_' + #billRequestDto.billNo + '_' + #billRequestDto.orderNo + '_' + #billRequestDto.contNo + #billRequestDto.billStatus + '_'" +" + '_' + #billRequestDto.billType + '_' + #billRequestDto.channelName + '_' + #billRequestDto.productName + '_' + #billRequestDto.settleSubjectCode" +" + '_' + #billRequestDto.contractCompanyCode + '_' + #billRequestDto.coInsuranceName + '_' + #billRequestDto.billBeginDate " +" + '_' + #billRequestDto.billEndDate+ '_' + (#billRequestDto.addBillSidList != null ? #billRequestDto.addBillSidList.toString() : '')")
访问接口后查询缓存:
六、注意事项
尽管@Cacheable
注解非常强大,但在使用时还是需要注意一些问题:
1.数据一致性:如果你的数据经常变化,那么你需要考虑数据一致性的问题。你可以使用@CacheEvict
或@CachePut
注解来清除或更新缓存。使用@Cacheable
注解的确可以提高应用程序的性能,因为它可以避免重复的数据库查询。然而,如果你的数据经常变化,那么缓存的数据可能会很快就过时了。在这种情况下,你需要考虑以下几点:
-
缓存过期策略:你可以设置缓存的过期时间,使得缓存的数据在一段时间后自动清除。这样,下次查询时,将会从数据库中获取最新的数据。缺点是,如果数据在缓存过期之前就已经变化了,那么你仍然可能会得到过时的数据。
-
使用@CacheEvict注解:当数据发生变化时(例如,在更新或删除操作后),你可以使用
@CacheEvict
注解来清除缓存。例如:@CacheEvict(value = "users", key = "#user.id") public void updateUser(User user) {//... }
这样,每次更新用户信息后,对应的缓存将被清除。下次查询时,将会从数据库中获取最新的数据。缺点是,你需要在所有可能改变数据的操作后都清除缓存,这可能会使代码变得复杂。
-
使用@CachePut注解:
@CachePut
注解会在每次方法调用后更新缓存。这意味着,即使数据发生了变化,缓存中的数据也总是最新的。例如:@CachePut(value = "users", key = "#user.id") public User updateUser(User user) {//...return user; }
注意,
@CachePut
注解的方法应该返回更新后的对象。这样,返回的对象将被用来更新缓存。缺点是,这可能会影响性能,因为每次方法调用都会更新缓存。
2.数据一致性缓存穿透:如果你的方法可能会接收到大量的无效参数,那么你需要考虑缓存穿透的问题。你可以在方法内部检查参数的有效性,或者使用@Cacheable
注解的unless
属性来排除某些结果。
3.缓存雪崩:如果你的缓存有过期时间,那么你需要考虑缓存雪崩的问题。你可以使用随机的过期时间,或者使用二级缓存来避免大量的缓存同时过期。
4.适合查询不变的数据:如果复杂数据结构的数据的状态经常改变,不建议接口缓存。
七、总结
在本文中,我们详细介绍了Spring中的@Cacheable
注解。通过使用@Cacheable
注解,我们可以轻松地将方法的执行结果存储在缓存中,从而提高应用程序的响应速度。然而,使用@Cacheable
注解时,还需要注意数据一致性、缓存穿透和缓存雪崩等问题。
希望本文能够帮助你更好地理解和使用Spring中的@Cacheable
注解。如果你有任何问题或建议,欢迎在评论区留言。
👉 💐🌸 公众号请关注 "果酱桑", 一起学习,一起进步! 🌸💐
相关文章:

Spring缓存深入解析:@Cacheable的使用详解
摘要:在本文中,我们将深入研究Spring框架中的Cacheable注解。我们会通过详细的Java示例,探讨如何使用这个功能强大的注解来提升应用程序性能。 一、什么是缓存? 在计算机科学中,缓存是一种存储技术,用于保…...

软件配置安装(破解)--- jdk下载配置
下载jdk 如果有oracle账号的话直接登录下载你想要的版本 不然可以尝试镜像站 HUAWEI镜像:https://repo.huaweicloud.com/java/jdk/ 安装 配置(细节) 这里的JAVA_HOME就是java的家,也就是解压(或安装)之后的java的目录ÿ…...

idea使用docker生成镜像(打包镜像,导入镜像,导出镜像)
1:先下载安装dockerdesktop,安装成功后 2: 在cmd执行docker -v,查看安装的docker版本 C:\Users\dell>docker -v Docker version 24.0.5, build ced09963:需要启动 dockerdesktop应用,才算启动docker&a…...

wazuh环境配置
目录 一、wazuh的安装 1.1官方仓库安装 1.2虚拟机OVA安装 1.2.1 然后执行下面命令 1.2.2 这里还要下载脚本和config.yml配置文件,用来生成证书编辑 1.2.3然后编辑config.yml文件,将下面的三个IP地址改为一样的 1.2.4运行./wazuh-certs-tool.sh以…...
【Linux】Linux下常用压缩解压缩指令及选项小结
0x00 前言 版本信息:Ubuntu 18.04.6 LTS 最后更新日期:2023.8.22 0x01 Linux下常用压缩解压缩指令小结 1.gzip指令 gzip file:压缩file文件为file.gz ,但是只能压缩文件不能压缩目录,且不保留源文件。若想打包目录…...

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器
香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息,他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比,这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…...
A 题:震源属性识别模型构建与震级预测 :代码分析:
问题 1: 针对附件 1~8 中的地震波数据,找出一系列合适的指 标与判据,构建震源属性识别模型,进行天然地震事件(附件 1~7) 与非天然地震事件(附件 8)的准确区…...

源码分析CompletableFuture使用默认线程池ForkJoinPool的弊端
先说结论: 假如有20CompletableFuture任务并发执行时,都使用默认线程池ForkJoinPool,但cpu的核心数又小于3,那么就会新建20个线程(不使用默认线程池了),这20个线程相互竞争cpu资源和内存&#x…...

连接pgsql数据库 sslmode sslrootcert sslkey sslcert 参数的作用
sslmode 参数的作用 sslmode 参数用于指定数据库连接时使用的 SSL 加密模式。SSL(Secure Sockets Layer)是一种加密协议,用于保护数据在客户端和服务器之间的传输过程,以增加数据传输的安全性。sslmode 参数可以设置不同的值&…...
从零学算法3
3.给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”&…...

宠物小程序开发
在当今社会,宠物已成为许多人生活中不可或缺的一部分。宠物市场的持续增长为创业者提供了巨大的商机。然而,作为一个创业者,要在竞争激烈的宠物市场中脱颖而出并不容易。因此,开发一个专属于自己的宠物小程序成为了解决这一难题的…...

07-Vue基础之综合案例——小黑记事本
个人名片: 😊作者简介:一名大二在校生 🤡 个人主页:坠入暮云间x 🐼座右铭:懒惰受到的惩罚不仅仅是自己的失败,还有别人的成功。 🎅**学习目标: 坚持每一次的学习打卡 文章…...

vite4+vue3+electron23.3+ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包
vite4vue3electron23.3ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包 主要包依赖 "electron-store": "^8.1.0", //全局数据状态管理,可选择性安装"electron": "23.3.8","electron-builder": &q…...

限制 el-input 输入 emoji
1. 电脑如何输入 emoji 表情 ? 快捷键 win; 或 win. 2. 代码实现 <template><el-input v-model"input" placeholder"请输入内容" input"inputChange"></el-input> </template><script> export default {name: D…...
【AI】解决Number_Words的安装和使用
It appears that you encountered an error while trying to install the “Numbers_Words” package using the specific version 0.18.2 of the PEAR channel. The error message indicates that there was a problem unpacking the “Math_BigInteger-1.0.3” package, whi…...
开启MySQL的binlog日志
在/etc/my.cnf增加如下配置 #binlog相关 log-bin /testdata/mysql/log/bin/mysql-bin expire_logs_days 7 binlog-format ROW binlog_cache_size 4M max_binlog_cache_size 20G binlog_rows_query_log_events 1 binlog_row_image FULL sync_binlog 1 log_bin_trust_fun…...
【支付宝小程序】支付宝小程序自定义组件技术教程
🦖我是Sam9029,一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 **🐱🐉🐱🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,…...
CSDN编程题-每日一练(2023-08-23)
CSDN编程题-每日一练(2023-08-23) 一、题目名称:圆小艺二、题目名称:连续子数组的最大和三、题目名称:投篮一、题目名称:圆小艺 时间限制:1000ms内存限制:256M 题目描述: 最近小艺酱渐渐变成了一个圆滑的形状-球!! 小艺酱开始变得喜欢上球! 小艺酱得到n个同心圆。 …...

解决:Appium Inspector刷新页面一直加载转圈
目录 问题:Appium Inspector刷新页面一直加载转圈 解决办法: 1.进入设置页面-电池-后台耗电管理 2.找到下面3个应用,修改为允许后台高耗电 问题:Appium Inspector刷新页面一直加载转圈 1、手机进行操作后,Appium I…...

Apache Doris 入门教程34:Join 优化
Bucket Shuffle Join Bucket Shuffle Join 是在 Doris 0.14 版本中正式加入的新功能。旨在为某些 Join 查询提供本地性优化,来减少数据在节点间的传输耗时,来加速查询。 它的设计、实现和效果可以参阅 上面的图片展示了Bucket Shuffle Join的工作原理…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...