当需要在一个方法中清除多个缓存时,@CacheEvict注解能否实现这个需求

news2025/5/18 22:16:09

想清除Redis中的多个缓存数据,如何实现?

@CacheEvict清除一个缓存,但现在想知道如何处理多个缓存的情况。场景:可能有一个更新用户信息的方法,这个方法执行后,不仅需要清除某个特定的用户缓存,还可能影响到其他相关的缓存,比如用户列表缓存或者某种组合查询的缓存。例如,更新用户信息后,用户详细信息的缓存需要清除,同时所有用户的列表缓存也需要更新,这时候就需要同时清除多个缓存条目。

Spring的@CacheEvict注解的功能。这个注解默认每次只能指定一个缓存名称(value或cacheNames)和一个键(key)。因此,如果直接使用单个@CacheEvict注解,是无法同时清除多个不同缓存名称或不同键的缓存的

解决方式:

  1. 使用多个@CacheEvict注解​:Spring允许在同一个方法上使用多个缓存相关的注解,比如同时使用多个@CacheEvict,每个注解指定不同的缓存名称和键。例如,一个注解清除用户缓存,另一个清除用户列表缓存。

  2. 使用@Caching组合注解​:@Caching注解可以组合多个缓存操作,包括Cacheable、CachePut和CacheEvict。用户可以在@Caching的evict属性中包含多个@CacheEvict,每个指定不同的缓存名称和键。

  3. 清除整个缓存区域​:如果多个缓存条目都属于同一个缓存名称(比如同一个value),可以通过设置allEntries=true来清除该缓存名称下的所有条目。但如果需要跨不同的缓存名称,这种方法就不适用了。

具体实现方式如下

1.@Caching组合注解

通过 @Caching 注解将多个 @CacheEvict 组合在一起,支持 ​跨不同缓存名称(value)和键(key)的批量清除

@Caching(evict = {
    @CacheEvict(value = "userList", key = "'allUsers'"),      // 清除用户列表缓存
    @CacheEvict(value = "userStats", key = "'activeCount'"),  // 清除统计信息缓存
    @CacheEvict(value = "userDetail", key = "#userId")       // 清除用户详情缓存
})
public void updateUser(Long userId) {
    // 1. 更新数据库
    userRepository.updateUser(userId);
    
    // 2. 其他业务逻辑...
}

2.使用多个@CacheEvict注解

直接在方法上叠加多个 @CacheEvict 注解,适用于简单场景。

@CacheEvict(value = "userList", key = "'allUsers'")
@CacheEvict(value = "userDetail", key = "#userId")
public void updateUser(Long userId) {
    // 数据库更新操作
}

3.清理整个缓存区域

如果某个缓存名称(value)下的所有键都需要清除,可以使用 allEntries = true

// 清除 userList 缓存下的所有键
@CacheEvict(value = "userList", allEntries = true)
public void refreshAllUserRelatedCache() {
    // 方法体可为空
}
适用场景
  • 当缓存键难以枚举(如分页缓存)
  • 需要批量清除关联缓存

4.动态生成多缓存键

通过 SpEL 表达式动态生成多个键值,结合 @CacheEvict 实现批量清除。

// 清除用户详情缓存及其关联缓存
@CacheEvict(value = "userDetail", key = "#userId")
@CacheEvict(value = "userRelations", key = "'relations_' + #userId")
public void updateUserWithRelations(Long userId) {
    // 更新用户及其关联数据
}

5.事件驱动缓存清除(高级)

通过 Spring 事件机制监听数据库变更,自动触发多缓存清除。

实现步骤

(1)定义自定义事件

public class UserUpdateEvent {
    private Long userId;
    // 构造函数、Getter/Setter...
}

(2)发布事件

@Service
public class UserService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void updateUser(Long userId) {
        userRepository.updateUser(userId);
        eventPublisher.publishEvent(new UserUpdateEvent(userId));
    }
}

(3)监听事件并清除缓存

@Component
public class UserCacheListener {
    @Autowired
    private CacheManager cacheManager;
    
    @EventListener
    public void handleUserUpdate(UserUpdateEvent event) {
        // 清除 userDetail 缓存
        cacheManager.getCache("userDetail").evict(event.getUserId());
        
        // 清除 userList 缓存
        cacheManager.getCache("userList").clear();
    }
}

性能与一致性建议

场景推荐方案注意事项
精确清除少量缓存@Caching + 多个 @CacheEvict确保键值正确
批量清除关联缓存allEntries = true避免对大型缓存使用
高频更新场景TTL 过期 + 延迟双删结合 Redis 的 EXPIRE 命令
分布式环境事件驱动 + 消息队列确保缓存清除操作传播到所有节点

完整示例:用户更新操作清除多个缓存

@Service
public class UserService {

    // 更新用户并清除关联缓存
    @Caching(evict = {
        @CacheEvict(value = "userDetail", key = "#userId"),
        @CacheEvict(value = "userList", key = "'allUsers'"),
        @CacheEvict(value = "userSearch", keyGenerator = "searchKeyGenerator")
    })
    public User updateUser(Long userId, User newUser) {
        // 1. 更新数据库
        User updatedUser = userRepository.save(newUser);
        
        // 2. 记录操作日志(与缓存无关)
        log.info("User {} updated", userId);
        
        return updatedUser;
    }
    
    // 自定义键生成器
    @Bean
    public KeyGenerator searchKeyGenerator() {
        return (target, method, params) -> "search_" + params[0];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎

在生成式AI与行业大模型的双重驱动下,人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策,AI技术渗透至产品研发、运营的全链条,推动效率跃升与创新模式变革。然而,面对AI技术迭代的爆发期&#xff0…

对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景

文章目录 对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景HTTP-REST 与 gRPC 的核心区别gRPC 的优缺点HTTP-REST 的优缺点适用场景 模糊点什么是 Protobuf?HTTP/2 会将 HTTP 消息拆分并封装为二进制帧,那还能过使用 HTTP/2 构建 RESTful …

Git - 1( 14000 字详解 )

一: Git 初识 1.1 提出问题 在工作或学习中,我们常常会面临文档管理的问题,尤其是在编写各种文档时。为了防止文档丢失或因更改失误而无法恢复,我们常常会创建多个版本的副本,例如:“报告-v1”、“报告-v…

TCPIP详解 卷1协议 九 广播和本地组播(IGMP 和 MLD)

9.1——广播和本地组播(IGMP 和 MLD) IPv4可以使用4种IP地址:单播(unicast)、任播(anycast)、组播(multicast)和广播(broadcast)。 IPv6可以使用…

16.1 - VDMA视频转发实验之TPG

文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项 4 软件设计4.1 注意事项4.2 工程源码4.2.1 main.c文件 1 实验任务 基于14.1,使用Xilinx TPG(Test Pattern Generator) IP提供视频源,将视频数据通过VDMA写入PS…

cocos creator 3.8 下的 2D 改动

在B站找到的系统性cocos视频教程,纯2D开发入门,链接如下: zzehz黑马程序员6天实战游戏开发微信小程序(Cocos2d的升级版 CocosCreator JavaScript)_哔哩哔哩_bilibili黑马程序员6天实战游戏开发微信小程序(Cocos2d的升级版 CocosCreator Ja…

Unity光照笔记

问题 在做项目中遇到了播放中切换场景后地面阴影是纯黑的问题,不得不研究一下光照。先放出官方文档。 Lighting 窗口 - Unity 手册 播放中切换场景后地面阴影是纯黑 只有投到地面的阴影是纯黑的。且跳转到使用相同Terrain的场景没有问题。 相关文章&#xff1a…

嵌入式学习的第二十天-数据结构-调试+链表的一般操作

一、调试 1.一般调试 2.找段错误 二、链表的一般操作 1.单链表的修改 int ModifyLinkList(LinkList*ll,char*name,DATATYPE*data) {DATATYPE * tmp FindLinkList(ll, name);if(NULL tmp){return 1;}memcpy(tmp,data,sizeof(DATATYPE));return 0; } 2.单链表的销毁 int D…

家具制造行业的现状 质检LIMS如何赋能家具制造企业质检升级

在家具制造行业,从原木切割到成品出厂,质检环节贯穿始终 —— 木材含水率是否达标、板材甲醛释放量是否合规、涂层耐磨性能否通过标准…… 这些看似琐碎的检测项目,实则是企业把控产品品质、规避市场风险的核心关卡。传统人工质检模式在效率、…

idea整合maven环境配置

idea整合maven 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】:每个知识点,都是写出代码…

无偿帮写毕业论文(看不懂的可以私信博主)

以下教程教你如何利用相关网站和AI免费帮你写一个毕业论文。毕竟毕业论文只要过就行,脱产学习这么多年,终于熬出头了,完成毕设后有空就去多看看亲人好友,祝好! 一、找一个论文模板 废话不多说,先上干货Ov…

小白成长之路-vim编辑

文章目录 Vim一、命令模式二、插入模式3.a:进入插入模式,在当前光标的后一个字符插入![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/fd293c3832ed49e2974abfbb63eeb5bb.png)4.o: 在当前光标的下一行插入5.i:在当前光标所在字符插入,返回命令模…

【常用算法:排序篇】7.算法魔法与面试秘籍:从趣味排序到实战通关

一、趣味排序算法:突破常规的思维火花 1. 睡眠排序(Sleep Sort)—— 时间维度的魔法 核心思想:利用多线程休眠时间模拟数值大小,自然输出有序结果。Python示例:import threading import timedef sleep_so…

Android | IOS — Solox性能测试

文章目录 Solox性能测试1. 前置条件2. 软件图片 Solox性能测试 1. 前置条件 安装Python:3.10.0以上版本: Windows:Python官网 安装 SoloX python -m solox2. 软件图片 软件图片 报告分析:

Midjourney 最佳创作思路与实战技巧深度解析【附提示词与学习资料包下载】

引言 在人工智能图像生成领域,Midjourney 凭借其强大的艺术表现力和灵活的创作模式,已成为设计师、艺术家和创意工作者的核心工具。作为 CSDN 博主 “小正太浩二”,我将结合多年实战经验,系统分享 Midjourney 的创作方法论&#x…

工具篇-扣子空间MCP,一键做游戏,一键成曲

一、登陆扣子空间 地址如下: 扣子空间 打开,然后登陆扣子 登陆之后快速开始: 二、生成游戏 小试牛刀,我们让它做一个打地鼠的游戏: 已经开始设计制作: 制作完成: 三、制作音乐 新…

5.6 - 5.9 MySQL

数据库:存储和管理数据的仓库DB。 数据库管理系统:操纵和管理数据库的大型软件DBMS。 关系型数据库 一个数据库内可以创建多张表,在一个表内能存放多个数据。 SQL语句: DDL: 存储字符串用varchar。(类似于…

C# WinForm 如何高效地将大量数据从 CSV 文件导入 DataGridView

如果你有非常多的csv文件,每个文件包含N多行与M多列,如:18000 行和 27 列。现在,想制作一个 Windows 窗体应用程序,导入它们并在 datagridview 中显示,然后进行一些数学运算。可是,发现数据导入…

SQLPub:一个提供AI助手的免费MySQL数据库服务

给大家介绍一个免费的 MySQL 在线数据库环境:SQLPub。它提供了最新版本的 MySQL 服务器测试服务,可以方便开发者和测试人员验证数据库功能,也可以用于学习 MySQL。 免费申请 在浏览器中输入以下网址: https://sqlpub.com/ SQLP…

URP相机如何将场景渲染定帧模糊绘制

1)URP相机如何将场景渲染定帧模糊绘制 2)为什么Virtual Machine会随着游戏时间变大 3)出海项目,打包时需要勾选ARMv7吗 4)Unity是手动还是自动调用GC.Collect 这是第431篇UWA技术知识分享的推送,精选了UWA社…