SpringBoot 集成Caffeine实现一级缓存

SpeingBoot 集成Caffeine实现一级缓存使我们经常遇到的场景。今天我们具体分享一下:

首先 Caffeine 作为一级缓存,它是 Spring 5.x 默认的本地缓存实现,性能优于 Guava Cache,且支持过期时间设置。缓存执行的流程图如下:

1、pom文件引入包

         <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.9.3</version> <!-- 兼容 Spring Boot 2.3.5 的版本 --></dependency>

2、换成配置类

 import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;@Configuration
@EnableCaching  
public class CacheConfig {/**Caffeine 配置参数:expireAfterWrite:写入后多久过期expireAfterAccess:最后访问后多久过期maximumSize:缓存的最大元素数量weakKeys/weakValues:使用弱引用,支持垃圾回收**/@Beanpublic CacheManager cacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES)//可以选多种时间.maximumSize(10));//最大缓存个数// 配置特定缓存(超时时间5分钟,到时间自动置为null)cacheManager.setCacheNames(java.util.Arrays.asList("timeoutParam"));return cacheManager;}
}

1)配置多个缓存

@Beanpublic CacheManager cacheManager() {SimpleCacheManager cacheManager = new SimpleCacheManager();// 配置不同的缓存区域(可根据业务需求设置不同的超时时间)cacheManager.setCaches(Arrays.asList(new CaffeineCache("timeoutParams",Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES) // 5分钟过期.maximumSize(100).build()),new CaffeineCache("longTermCache",Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS) // 1小时过期.maximumSize(1000).build())));return cacheManager;}

不同缓存数据的超时时间可能不一样,因此需要设置不同的缓存。 

3、业务层实现

import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;@Service
public class MyService {// 获取参数(从缓存读取,若无则执行方法并缓存结果)unless:条件表达式,满足条件则不缓存(如 #result == null)@Cacheable(value = "timeoutParams", key = "#paramName")public String getParam(String paramName) {// 模拟从数据库或其他数据源获取System.out.println("从数据源加载参数: " + paramName);return loadParamFromDB(paramName);}// 更新参数(强制刷新缓存,即使缓存存在)@CachePut(value = "timeoutParams", key = "#paramName")public String updateParam(String paramName, String newValue) {// 保存到数据库saveParamToDB(paramName, newValue);return newValue;}// 清除缓存:调用此方法后,指定缓存键将被删除@CacheEvict(value = "timeoutParams", key = "#paramName")public void clearParam(String paramName) {System.out.println("清除缓存: " + paramName);// 通常无需方法体,仅用于触发缓存清除}// 模拟数据库操作private String loadParamFromDB(String paramName) {// 实际项目中从数据库或其他数据源获取return "默认值";}private void saveParamToDB(String paramName, String value) {// 实际项目中保存到数据库}
}

 4、控制层调用

       // 第一次调用,会从数据源加载String value1 = myService.getParam("testParam");System.out.println("第一次获取: " + value1);// 第二次调用,会从缓存获取String value2 = myService.getParam("testParam");System.out.println("第二次获取: " + value2);

5、通过key获取数据

1)通过key手动插入

@Service
public class ManualCacheService {@Autowiredprivate CacheManager cacheManager;public void initCacheManually(String key, Object value) {Cache cache = cacheManager.getCache("paramCache");if (cache != null) {cache.put(key, value);  // 手动放入缓存System.out.println("手动初始化缓存: " + key + " = " + value);}}
}

2)手动获取

@Service
public class CacheAccessService {@Autowiredprivate CacheManager cacheManager;public Object getValueManually(String key) {Cache cache = cacheManager.getCache("paramCache");if (cache != null) {Cache.ValueWrapper wrapper = cache.get(key);return wrapper != null ? wrapper.get() : null;}return null;}
}

 

6、通过注解获取数据(注意伪代码)

@Service
public class JTServiceImpl {@Servicepublic void someMethod() {// 自调用 - 导致缓存失效String token = this.getGlobalToken("token123"); }@Cacheable(value = "timeoutGlobalToken", key = "#globalToken")public String getGlobalToken(String globalToken) {// 实际获取token的逻辑}
}

注意:注解失效原因及解决方案

原因分析:

  1. Spring AOP 工作原理

    • Spring 的缓存功能(包括 @Cacheable)是基于 AOP 代理实现的

    • 当调用 @Cacheable 方法时,实际调用的是代理对象的方法,不是原始对象的方法

  2. 自调用问题(Self-Invocation)

    • 当同一个类中的方法 A 直接调用方法 B(带 @Cacheable 注解)时

    • 调用发生在原始对象内部,绕过了 Spring 代理

    • 导致 @Cacheable 注解完全失效

解决方案:将缓存方法移到另一个Service中

// 新建专门处理缓存的服务
@Service
public class TokenCacheService {@Cacheable(value = "timeoutGlobalToken", key = "#globalToken")public String getGlobalToken(String globalToken) {// 实际获取token的逻辑return fetchTokenFromSource(globalToken);}private String fetchTokenFromSource(String globalToken) {// 从数据库/API获取token的实现}
}

调用方:

// 原服务调用缓存服务
@Service
public class JTServiceImpl {@Autowiredprivate TokenCacheService tokenCacheService;public void businessMethod() {// 跨类调用 - 触发缓存String token = tokenCacheService.getGlobalToken("token123");}
}

这是一个比较常用的解决方案。 

 8、获取所有缓存信息

@GetMapping("/cache/param")
public Map<Object, Object> getCacheEntries() {Cache cache = cacheManager.getCache("paramCache");if (cache == null) {return Collections.emptyMap();}com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache = (com.github.benmanes.caffeine.cache.Cache<Object, Object>) cache.getNativeCache();return new HashMap<>(nativeCache.asMap());
}

到此,SpringBoot 集成Caffeine实现一级缓存分享完成,下篇我们会继续分享此种缓存实现的细节,敬请期待!

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

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

相关文章

中科米堆3D自动扫描检测系统三维数字化智能解决方案

3D自动扫描检测系统基于先进的光学、激光或结构光等测量技术&#xff0c;能够快速、准确地获取工件的三维几何数据。在检测过程中&#xff0c;系统通过向被测工件投射特定的光模式&#xff0c;利用高分辨率相机捕捉工件表面的反射光信息&#xff0c;再经过复杂的算法处理&#…

Unity3d中使用Mirror进行自定义消息通信

一、服务端&#xff1a; 1.创建服务端脚本MyServer.cs 继承自NetworkManager类 using Mirror; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class MyServer : NetworkManager {[Header(&quo…

Odoo 18 固定资产管理自动化指南

如何在Odoo 18中实现资产管理自动化 1. 创建资产模型实现资产管理自动化 使用 Odoo 18 的会计模块&#xff0c;资产的创建和确认可轻松实现自动化。这将使资产管理变得更加简单高效。使用资产自动化功能&#xff0c;一旦验证相关产品的供应商账单&#xff0c;Odoo将自动生成并…

如何轻松地将音乐从 iPhone 传输到 Mac?

想把音乐从 iPhone 传输到 Mac 吗&#xff1f;这很常见&#xff0c;无论你是想更换设备、备份收藏&#xff0c;还是只想在更大的屏幕上欣赏喜爱的歌曲。幸运的是&#xff0c;有 6 种有效的方法可以完成这项工作&#xff0c;具体取决于你喜欢使用的工具。让我们开始吧。 第 1 部…

人工智能——解读AI智慧课堂系统解决方案【附全文阅读】

该文档是 AI 智慧课堂系统解决方案,聚焦教育信息化需求,通过 AI 技术与教学深度融合,解决传统课堂考勤效率低、资源管理难、分析不精准等问题。 方案以课堂为核心,构建 “背景分析 - 方案设计 - 优势价值” 框架,技术架构涵盖教师摄像机、学生抓拍机、智能录播主机等设备,…

使用Nginx的RTMP模块进行直播流转HLS时,处理和预防`.ts`文件过多

当使用Nginx的RTMP模块进行直播流转HLS时,如果长时间运行或处理大量流媒体内容,可能会遇到.ts文件累积过多的问题。这不仅会占用大量的磁盘空间,还可能影响系统性能。以下是一些处理和预防.ts文件过多的方法: 1. 配置HLS清理 Nginx RTMP模块允许配置HLS片段的过期时间,这…

结构体解决冒泡排序

设计英雄的结构体 //1、设计结构体 struct Hero {string name;//姓名int age;//年龄string sex;//性别 };创建英雄的数组 //2、创建数组存放英雄 struct Hero Array[5] {{"刘备", 34 ,"男"},{"关羽", 45 ,"男"},{"张飞",…

spring-webmvc @RequestParam 典型用法

典型用法 基本使用 HTTP请求参数绑定到方法参数 GetMapping("/users") public String getUsers(RequestParam String name) {return "Hello, " name; }请求&#xff1a;/users?nameJohn 输出&#xff1a;Hello, John-----GetMapping("/filter&qu…

AntDesignPro前后端权限按钮系统实现

目录 Ant Design Pro 后端接口权限按钮系统 系统架构图 前端实现 权限按钮组件 (AuthButton.tsx) 权限钩子 (useAccess.ts) 权限服务 (permission.ts) 产品列表页面 (ProductList.tsx) 后端接口设计 (Node.js Express 示例) 权限接口控制器 (permissionController.js…

RAG工程落地:处理文档中表格数据

在 RAG&#xff08;Retrieval-Augmented Generation&#xff09;工程落地过程中&#xff0c;处理文档中的表格数据 是一个非常重要但复杂的问题&#xff0c;特别是针对技术文档、报告、论文等结构化强的资料。比如PDF文档里的表格数据&#xff0c;如下&#xff1a; RAG处理表格…

大模型在肺癌预测及个性化诊疗方案中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 1.3 国内外研究现状 二、大模型预测肺癌的原理与方法 2.1 大模型概述 2.2 数据收集与预处理 2.3 特征工程 2.4 模型训练与优化 三、术前预测与方案制定 3.1 病情评估 3.1.1 肿瘤大小、位置及分期预测 3.1.…

如何高效分享WordPress博客文章

在当今信息过载的时代&#xff0c;写好一篇优秀的 WordPress 博客文章只是起点&#xff0c;如何有效地分享给更多读者才是成功的关键所在。对于新手用户而言&#xff0c;选择合适的工具和平台尤为重要。现在许多服务器提供商支持一键安装WordPress功能&#xff0c;比如 Hosteas…

以孝治家有机农业生态文明考察组赴邯郸心田农场考察学习

按照2025年中共中央、国务院印发了关于《乡村全面振兴规划&#xff08;2024—2027年&#xff09;》的战略部署。根据《乡村全面振兴规划》提出的“坚持人与自然和谐共生。牢固树立和践行绿水青山就是金山银山的理念&#xff0c;落实节约优先、保护优先、自然恢复为主的方针&…

解决el-input无法输入的问题 vue2+element el-input

问题描述: 在el-dialog中el-form组件来做表单提交 中文输入模式: 在初次输入的时候能输入内容 但是再次输入无法更改内容 英文输入模式: 只能输入一个英文 很多文章都是说 是双向绑定的问题 但是我仔细看了 变量的双向绑定确实没毛病 直到我发现了是因为我el-input中的图…

16_集成学习

描述 集成学习&#xff08;Ensemble Learning&#xff09;是一种通过结合多个模型的预测结果来提高整体性能的技术。集成学习的核心思想是通过多个弱学习器的组合&#xff0c;可以构建一个强学习器。 sklearn中常见的集成学习算法&#xff1a; Bagging&#xff1a;通过自助采…

学习STC51单片机43(芯片为STC89C52RCRC)智能小车9(语音识别小车)

每日一言 不必与他人比较速度&#xff0c;你走的每一步都在书写自己的传奇。 案例&#xff1a;语音识别小车 这个是最后一个功能了&#xff0c;其实就是用语音功能让小车自己切换各种模式&#xff0c;当然了我们需要先学习一下语音模块 硬件&#xff1a;SU-03T 这个叫做非特定…

Android 中 解析 XML 字符串的几种方式

在 Android 开发中&#xff0c;解析 XML 文件有多种方式&#xff0c;每种方式都有其特点和适用场景。常见的 XML 解析方式有 DOM 解析、SAX 解析 和 XmlPullParser 解析。 1、DOM 解析 DOM&#xff08;Document Object Model&#xff09;解析是一种基于树结构的解析方式&#…

云端算力革命:川翔云电脑如何重新定义创作自由

在设计与科技深度融合的时代&#xff0c;高性能硬件的桎梏正成为创意释放的最大障碍。川翔云电脑以云端算力为支点&#xff0c;通过弹性算力、高效存储、多端接入三大核心优势&#xff0c;让顶级 GPU 资源触手可及。 一、核心优势&#xff1a;突破物理极限的云端工作站 弹性算…

1.容器技术与docker环境部署

一&#xff1a;docker概述 因为 Docker 轻便、快速的特性&#xff0c;可以使应用达到快速迭代的目的。每次小的变更&#xff0c;马上就可以看到效果&#xff0c;而不用将若干个小变更积攒到一定程度再变更。每次变更一小部分其实是一种非常安全的方式&#xff0c;在开发环境中…

关于 RSA:RSA 加密算法过程

RSA 是一种非对称加密算法&#xff0c;用“公钥”加密&#xff0c;用“私钥”解密&#xff0c;保证数据传输安全。 比喻理解&#xff1a;锁和钥匙 想象一下&#xff1a; 公钥是“上锁的锁”&#xff0c;别人可以用它锁住箱子&#xff08;加密&#xff09;&#xff0c;但打不开…