当前位置: 首页 > news >正文

Spring缓存深入解析:@Cacheable的使用详解

摘要:在本文中,我们将深入研究Spring框架中的@Cacheable注解。我们会通过详细的Java示例,探讨如何使用这个功能强大的注解来提升应用程序性能。

一、什么是缓存?

在计算机科学中,缓存是一种存储技术,用于保存经常使用的数据,以便在后续请求中快速访问。在Web开发中,缓存被广泛用于减少对数据库的访问,提高应用程序的响应速度。

二、Spring中的缓存抽象

Spring提供了一种强大的缓存抽象,允许开发者通过简单的注解,将方法的执行结果存储在缓存中。这些注解包括@Cacheable@CacheEvict@CachePut等。在本文中,我们将重点关注@Cacheable注解。

三、@Cacheable注解的使用

@Cacheable注解用于标记应该被缓存的方法。当一个方法被@Cacheable注解标记后,Spring会在调用该方法前检查缓存,如果缓存中存在对应的数据,就直接返回缓存的数据,而不执行方法。如果缓存中不存在对应的数据,Spring会执行方法,然后将返回结果存入缓存。

@Cacheable注解有两个重要的属性:valuekeyvalue用于指定缓存的名称,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的使用详解

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

软件配置安装(破解)--- jdk下载配置

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

idea使用docker生成镜像(打包镜像,导入镜像,导出镜像)

1&#xff1a;先下载安装dockerdesktop&#xff0c;安装成功后 2&#xff1a; 在cmd执行docker -v&#xff0c;查看安装的docker版本 C:\Users\dell>docker -v Docker version 24.0.5, build ced09963&#xff1a;需要启动 dockerdesktop应用&#xff0c;才算启动docker&a…...

wazuh环境配置

目录 一、wazuh的安装 1.1官方仓库安装 1.2虚拟机OVA安装 1.2.1 然后执行下面命令 1.2.2 这里还要下载脚本和config.yml配置文件&#xff0c;用来生成证书​编辑 1.2.3然后编辑config.yml文件&#xff0c;将下面的三个IP地址改为一样的 1.2.4运行./wazuh-certs-tool.sh以…...

【Linux】Linux下常用压缩解压缩指令及选项小结

0x00 前言 版本信息&#xff1a;Ubuntu 18.04.6 LTS 最后更新日期&#xff1a;2023.8.22 0x01 Linux下常用压缩解压缩指令小结 1.gzip指令 gzip file&#xff1a;压缩file文件为file.gz &#xff0c;但是只能压缩文件不能压缩目录&#xff0c;且不保留源文件。若想打包目录…...

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…...

A 题:震源属性识别模型构建与震级预测 :代码分析:

问题 1&#xff1a; 针对附件 1&#xff5e;8 中的地震波数据&#xff0c;找出一系列合适的指 标与判据&#xff0c;构建震源属性识别模型&#xff0c;进行天然地震事件&#xff08;附件 1&#xff5e;7&#xff09; 与非天然地震事件&#xff08;附件 8&#xff09;的准确区…...

源码分析CompletableFuture使用默认线程池ForkJoinPool的弊端

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

连接pgsql数据库 sslmode sslrootcert sslkey sslcert 参数的作用

sslmode 参数的作用 sslmode 参数用于指定数据库连接时使用的 SSL 加密模式。SSL&#xff08;Secure Sockets Layer&#xff09;是一种加密协议&#xff0c;用于保护数据在客户端和服务器之间的传输过程&#xff0c;以增加数据传输的安全性。sslmode 参数可以设置不同的值&…...

从零学算法3

3.给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”&…...

宠物小程序开发

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

07-Vue基础之综合案例——小黑记事本

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;懒惰受到的惩罚不仅仅是自己的失败&#xff0c;还有别人的成功。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章…...

vite4+vue3+electron23.3+ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包

vite4vue3electron23.3ts桌面应用bs端开发 打包windows、linux、max三个系统的安装包 主要包依赖 "electron-store": "^8.1.0", //全局数据状态管理&#xff0c;可选择性安装"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…...

【支付宝小程序】支付宝小程序自定义组件技术教程

&#x1f996;我是Sam9029&#xff0c;一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 **&#x1f431;‍&#x1f409;&#x1f431;‍&#x1f409;恭喜你&#xff0c;若此文你认为写的不错&#xff0c;不要吝啬你的赞扬&#xff0c…...

CSDN编程题-每日一练(2023-08-23)

CSDN编程题-每日一练(2023-08-23) 一、题目名称:圆小艺二、题目名称:连续子数组的最大和三、题目名称:投篮一、题目名称:圆小艺 时间限制:1000ms内存限制:256M 题目描述: 最近小艺酱渐渐变成了一个圆滑的形状-球!! 小艺酱开始变得喜欢上球! 小艺酱得到n个同心圆。 …...

解决:Appium Inspector刷新页面一直加载转圈

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

Apache Doris 入门教程34:Join 优化

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

【神州数码】BGP路由器案例

SwitchB、SwitchC和SwitchD位于AS200中&#xff0c;SwitchA位于AS100中。SwitchA和SwitchB共享一个相同的网络段11.0.0.0。而SwitchB和SwitchD彼此物理上不相邻。 则SwitchA的配置如下&#xff1a; SwitchA(config)#router bgp 100SwitchA(config-router-bgp)#neighbor 11.1.1…...

gin框架实现大文件下载

在gin框架中实现大文件下载主要分为两个步骤&#xff1a; 将文件分块读取 由于大文件一次性读取会占用大量内存&#xff0c;容易导致内存溢出等问题&#xff0c;需要将文件分块读取&#xff0c;逐一发送给客户端。 在gin框架中&#xff0c;可以使用context.File方法向客户端…...

数据可视化-canvas-svg-Echarts

数据可视化 技术栈 canvas <canvas width"300" height"300"></canvas>当没有设置宽度和高度的时候&#xff0c;canvas 会初始化宽度为 300 像素和高度为 150 像素。切记不能通过样式去设置画布的宽度与高度宽高必须通过属性设置&#xff0c;…...

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞[2023-HW]

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞 一、漏洞描述二、漏洞影响三、网络测绘四、漏洞复现小龙POC检测: 五、 修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间…...

java反序列化泛型中json对象

使用 jackson的objectMapper 来实现 import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMa…...

Docker Compose一键管理容器

可以一键批量管理docker的容器。将所有需要创建的容器定义在compose配置文件中&#xff0c;通过一个命令一键可以创建并运行这些容器&#xff0c;而不需要一个一个启动。可以批量启动停止服务。 安装 #安装Docker-Compose并安装到/usr/local/bin/docker-compose curl -L &quo…...

API接口文档利器:Swagger 和 接口调试利器:Postman

2.接口相关工具 2.1API接口文档利器&#xff1a;Swagger 2.1.1Swagger介绍 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务 (https://swagger.io/)。 它的主要作用是&#xff1a; 使得前后端分离开发更加方便&#xff0…...

Redis手动实现分布式锁-Demo

1、pom文件依赖 <!--引入Redis操作依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 2、具体实现 package com.xch;import org.spring…...

BBS项目day04 文章详情页、点赞点菜、评论功能(根评论和子评论)、评论分页之刷新评论页面

一、路由 from django.contrib import admin from django.urls import path, re_path from app01 import views from django.views.static import serve from django.conf import settingsurlpatterns [path(admin/, admin.site.urls),# 注册path(register/, views.register)…...

【带着学Pytorch】1、pytorch的安装与入门

一、介绍与安装 1.1. pytorch优点: 上手简单:掌握语法和深度学习的概念,尤其是Numpy的使用与python的list切片有共同性。代码灵活:基本调用封装好的模块,动态图使编写更加灵活资源多: 硬件,软件,文档资料都很多。容易调试:动态运行在调试中可以观察数据的变化是否符…...

企业网站的首页设计模板/重庆百度seo代理

python 中国剩余定理 chinese-remainder-theorem1.题目2.编程思路及代码3.其他参考文献1.题目 描述 给出两个数组 num[0..k - 1] 和 rem[0..k - 1]. 在数组num[0..k - 1]中, 所有的元素都是互质的( gcd 为 1 ). 我们需要找到满足下列条件的最小正数 x:x % num[0] rem[0…...

江西移动网站/广告公司职位

tidb在插入一个新数据的时候报错&#xff1a; Table has no partition for value xxx 表明表中没有这个分区&#xff0c;需要新增 查一下新增语句 ALTER TABLE fans_medal ADD PARTITION (PARTITION p20200828 VALUES LESS THAN (20200829));然后再插入我需要的数据 解决&…...

可以做公司宣传的网站有哪些/互联网营销模式有哪些

1 概述 在平时开发中&#xff0c;git可以说是我们最不陌生的工具了。而且在提交线上代码或者是将自己功能分支上的代码给cherry-pick到预发分支上时&#xff0c;如果只提交了一个点那么直接cherry-pick就可以了&#xff0c;但是提交了很多点时&#xff0c;一个一个的cherry-pic…...

广州做网站好的公司/网络营销师资格证

CSS布局实例:上中下三行布局&#xff0c;上下定高&#xff0c;中间栏自适应浏览器高度&#xff0c;且内容垂直居中。本文代码在firefox 2.0 / winie 6/ win ie 7 /opera 8.5 cn/win safari测试通过。对于非ie内核浏览器&#xff0c;通过设定display:table、display:table-row和…...

查企业去哪个网站/网络推广员是干嘛的

我的上篇博客【我心目中的Asp.net核心对象】 讲述了一些我认为在Asp.net中比较重要的核心对象&#xff0c;以及演示了直接使用它们也能实现一个简单的服务响应。今天&#xff0c;我将继续把我认为Asp.net的另一些重要的内容拿出来与大家一起分享&#xff0c; 同时将使用本次所讲…...

青海省住房和建设厅网站首页/市场调研与分析

https://mp.weixin.qq.com https://mp.weixin.qq.com/s?__bizMzI3NzE0NjcwMg...