[004][缓存模块]Caffeine缓存自定义:构建灵活的Spring Boot缓存管理器

简介: 本文介绍Spring Boot中Caffeine缓存的灵活定制方案:通过自定义`FlexibleCaffeineCacheManager`,支持按缓存名(如users/products)独立配置过期策略、容量等参数,兼顾全局默认与个性化需求;结合线程安全创建器、属性合并机制及无缝Spring集成,实现高性能、易扩展、零侵入的本地缓存管理。(239字)

[004][缓存模块]Caffeine缓存自定义:构建灵活的Spring Boot缓存管理器

本项目代码:https://gitee.com/yunjiao-source/tutorials4j/tree/master/framework

在Spring Boot应用中,缓存是提升系统性能的重要手段。Caffeine作为高性能的本地缓存库,常与Spring的CacheManager抽象整合使用。然而,默认的CaffeineCacheManager仅支持全局统一的缓存配置(如过期时间、最大容量等),无法针对不同业务缓存进行差异化定制。本文将通过分析一个自定义的Caffeine缓存模块,展示如何实现支持“每个缓存独立配置”的灵活缓存管理器。

一、背景与目标

1.1 痛点

  • 业务缓存需求各异:用户会话缓存需要较短过期时间,商品目录缓存可设置较长过期时间且需要自动刷新。
  • 默认CaffeineCacheManager的配置是全局的,若想差异化,只能创建多个CacheManager实例,管理复杂。

1.2 设计目标

  • 支持全局默认配置 + 每个缓存名称可覆盖配置。
  • 复用Spring的CaffeineCacheManager,尽量减少侵入。
  • 提供线程安全的缓存管理器创建器,支持延迟初始化。
  • 保持与Spring Boot自动配置的无缝集成。

二、模块功能解析

项目提供了四个核心类,分别负责配置加载、工具方法、缓存管理器创建和个性化缓存生成。

2.1 CacheCaffeineConfiguration – Spring配置装配

@Configuration(proxyBeanMethods = false)
public class CacheCaffeineConfiguration {
   
    @Bean
    Caffeine<Object, Object> caffeine(CacheCaffeineProperties properties) {
   
        Caffeine<Object, Object> caffeine = Caffeine.newBuilder();
        CaffeineUtils.copyOption(caffeine, properties);
        return caffeine;
    }

    @Bean
    @ConditionalOnMissingBean(CaffeineCacheManagerCreator.class)
    CaffeineCacheManagerCreator caffeineCacheManagerCreator(Caffeine<Object, Object> caffeine,
                                              CacheCaffeineProperties properties) {
   
        return new CaffeineCacheManagerCreator(properties, caffeine);
    }
}
  • 作用:声明创建Caffeine实例的Bean,并通过CaffeineUtils将全局属性(如initialCapacitymaximumSize等)复制到构建器中。然后创建CaffeineCacheManagerCreator,它作为工厂负责生成最终的CacheManager
  • 亮点:使用@ConditionalOnMissingBean允许用户覆盖默认的创建器实现,提供扩展点。

2.2 CaffeineUtils – 配置复制工具

public interface CaffeineUtils {
   
    static void copyOption(Caffeine<Object, Object> caffeine, CaffeineOptions options) {
   
        caffeine.initialCapacity(options.getInitialCapacity())
                .maximumSize(options.getMaximumSize());
        if (options.getExpireAfterAccess() != null) {
   
            caffeine.expireAfterAccess(options.getExpireAfterAccess());
        }
        // ... 其他可选配置
        if (Objects.equals(Boolean.TRUE, options.getRecordStats())) {
   
            caffeine.recordStats();
        }
    }
}
  • 作用:将CaffeineOptions(包含过期策略、刷新间隔、统计开关等)批量设置到Caffeine构建器中。
  • 设计:声明为接口静态方法,便于复用;判空处理支持可选配置。

2.3 CaffeineCacheManagerCreator – 线程安全的单例创建器

public class CaffeineCacheManagerCreator implements Supplier<CaffeineCacheManager> {
   
    private final CacheCaffeineProperties properties;
    private final Caffeine<Object, Object> caffeine;
    private volatile CaffeineCacheManager instance;

    @Override
    public CaffeineCacheManager get() {
   
        if (instance != null) return instance;
        synchronized (this) {
   
            if (instance != null) return instance;
            instance = newInstance();
        }
        return instance;
    }

    public CaffeineCacheManager newInstance() {
   
        FlexibleCaffeineCacheManager manager = new FlexibleCaffeineCacheManager(properties);
        manager.setCaffeine(caffeine);
        return manager;
    }
}
  • 作用:实现Supplier接口,提供单例的CaffeineCacheManager。使用DCL(双重检查锁)保证线程安全,同时避免每次获取都创建新实例。
  • 优势:延迟加载,仅在首次调用get()时才真正构建缓存管理器;可作为Spring Bean直接注入,也可在需要时手动获取。

2.4 FlexibleCaffeineCacheManager – 核心个性化逻辑

public class FlexibleCaffeineCacheManager extends CaffeineCacheManager {
   
    private final CacheCaffeineProperties properties;

    @Override
    protected Cache<Object, Object> createNativeCaffeineCache(String name) {
   
        Map<String, CaffeineOptions> optionsMap = properties.getNamedCaches();
        if (MapUtils.isNotEmpty(optionsMap) && optionsMap.containsKey(name)) {
   
            CaffeineOptions caffeineOptions = optionsMap.get(name);
            caffeineOptions.mergeNullValue(properties); // 未设置的项回填全局值
            Caffeine<Object, Object> caffeine = Caffeine.newBuilder();
            CaffeineUtils.copyOption(caffeine, caffeineOptions);
            log.debug("初始化缓存: {}", name);
            return caffeine.build();
        }
        return super.createNativeCaffeineCache(name);
    }
}
  • 关键重写createNativeCaffeineCache(String name)CaffeineCacheManager中每个缓存创建时调用的方法。我们覆盖它,根据缓存名称从properties.getNamedCaches()中查找专属配置。
  • 配置合并caffeineOptions.mergeNullValue(properties)将未显式设置的属性(如expireAfterWrite为null)继承自全局配置,避免遗漏。
  • 降级处理:若没有专属配置,则调用父类方法,父类会使用默认的Caffeine实例(即全局配置)来构建缓存。

三、自定义扩展的设计精髓

3.1 属性模型设计

假设CacheCaffeineProperties包含:

  • 全局配置:initialCapacitymaximumSizeexpireAfterWrite等。
  • Map<String, CaffeineOptions> namedCaches:key为缓存名称,value为该缓存的个性化配置。

CaffeineOptions中定义与全局配置相同的字段,并提供一个mergeNullValue方法:对于自身为null的属性,从传入的默认配置中取值。

3.2 为什么需要CaffeineCacheManagerCreator

直接暴露FlexibleCaffeineCacheManager作为Bean也可以,但创建器的好处:

  1. 单例控制:确保整个应用只有一个CacheManager实例(Spring默认也如此,但通过Supplier可更明确控制创建时机)。
  2. 延迟初始化:避免在Spring容器启动阶段过早构建缓存(尤其是在缓存配置依赖外部动态参数时)。
  3. 测试友好:可mock或替换创建逻辑。

3.3 线程安全与性能

CaffeineCacheManager本身是线程安全的,但createNativeCaffeineCache会被多次调用(每个缓存名称调用一次)。FlexibleCaffeineCacheManager中每次有专属配置时都会新建一个Caffeine实例,这符合预期——不同缓存本就应拥有独立的配置和缓存实例。而CaffeineCacheManagerCreator中的DCL确保全局只有一个管理实例,避免了重复创建管理器的开销。

四、使用示例与配置

4.1 配置文件(application.yml)

tutorials4j:
  cache:
    caffeine:
      allow-null-values: false
      initial-capacity: 16
      maximum-size: 1000
      expire-after-write: 60s
      record-stats: true
      named-caches:
        users:
          expire-after-write: 30s
          maximum-size: 500
        products:
          expire-after-access: 10m
          refresh-after-write: 5m
  • 全局:默认写入后60秒过期,最大1000条。
  • users缓存:写入后30秒过期,最大500条(覆盖全局过期和最大容量)。
  • products缓存:访问后10分钟过期,写入后5分钟刷新(注意refreshAfterWrite需要搭配CacheLoader,此处仅为示例)。

4.2 启用缓存

@Configuration
@EnableCaching
public class MyCacheConfig {
   
    @Bean
    public CacheManager cacheManager(CaffeineCacheManagerCreator creator) {
   
        return creator.get(); // 获取单例缓存管理器
    }
}

或者在自动配置中直接使用CacheCaffeineConfiguration,它会自动装配创建器并暴露CacheManager

4.3 业务使用

@Service
public class ProductService {
   
    @Cacheable("products")
    public Product getProduct(Long id) {
    ... }

    @CacheEvict(cacheNames = "users", key = "#userId")
    public void evictUser(String userId) {
    ... }
}

此时products缓存将应用5分钟刷新+10分钟访问过期策略,而users缓存则使用30秒写入过期。

五、总结

通过上述设计,我们实现了:

  • 细粒度配置:每个缓存名称可定义独立的过期、容量等参数。
  • 线程安全且高效:单例管理器 + DCL,避免重复构造。
  • 易扩展:通过@ConditionalOnMissingBean允许用户替换创建器或缓存管理器。
  • 兼容Spring标准:继承CaffeineCacheManager,所有Spring缓存注解(@Cacheable等)无需改动。

Caffeine作为“现代Java本地缓存之王”,配合灵活的缓存管理器,能让你的应用在性能和业务需求之间取得完美平衡。希望本文的自定义实现能为你的项目提供有益的参考。

目录
相关文章
|
20天前
|
缓存 NoSQL Java
[006][缓存模块] 两级缓存实战:基于 Caffeine + Redis 的多级缓存设计与实现
本文介绍基于Caffeine(本地)+ Redis(分布式)的两级缓存实战方案,通过自定义`MultiLevelCache`与`MultiLevelCacheManager`,实现Spring Cache标准接口下的透明多级缓存:读优先本地(纳秒级)、未命中查Redis并回填;写同步更新两级,兼顾高性能与数据共享。代码开源可直接集成。
109 0
|
20天前
|
人工智能 运维 架构师
我在 AIP 智能体平台踩过的坑,都在这篇企业 AI 落地经验里了
软件架构师罗小东分享企业AI落地实战经验:聚焦AIP智能体平台建设中的真实坑点与解法——涵盖智能体全生命周期管理、多源知识库语义检索、MCP工具集成及多模型中立架构设计,强调“解决问题”而非堆砌功能。(239字)
|
1月前
|
人工智能 机器人 Shell
在公司蒸馏我之前,我先赛博飞升
OpenClaw(龙虾)是一款开源AI数字分身框架,可本地或云端部署,支持多模型接入(Claude、Qwen、Ollama等)及钉钉/飞书/Telegram等10+聊天平台。它不止聊天,还能操作浏览器、读写文件、执行命令,并通过插件实现“蒸馏人物”、自动化办公等高级能力,主打隐私可控、真能干活。
395 9
|
14天前
|
JSON 测试技术 API
别再卷提示词了,真正的护城河是你的私有Skill库
本文揭示AI工程化新趋势:提示词工程师岗位正快速消亡,真正壁垒在于构建私有Skill库。Skill将高频决策固化为可复用、带容错的低代码资产,深度绑定业务逻辑与私有配置,难以复制。文章对比OpenClaw、Cursor、Claude Code策略,提供从0到1建设路径,并指出三年后团队核心竞争力源于对业务的理解与Skill化沉淀。
|
12天前
|
运维 Java 开发者
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
本文详解基于Spring Boot的HTTP客户端统一配置方案,支持RestTemplate、RestClient与WebClient三种客户端,实现无侵入的日志记录(请求/响应头、状态码)、默认请求头注入(如X-Request-Id)、非2xx异常自动转换及链路追踪支持,全部通过Customizer与Filter机制自动装配,开箱即用,提升微服务调用可观测性与开发效率。(239字)
137 5
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
|
1月前
|
机器学习/深度学习 人工智能 图形学
🦞快在轻量化服务器上部署你的视觉龙虾吧——支持视觉识别到3D打印
彭博士打造的“视觉龙虾”系统,融合多视角3D重建、点云深度学习与参数化建模,支持手机拍照或自然语言输入,秒级生成可3D打印的STL模型。依托OpenClaw智能编排与阿里云轻量化部署,真正实现“想法→照片/文字→3D模型→实物”的端到端闭环,让3D打印零门槛。(239字)
449 8
🦞快在轻量化服务器上部署你的视觉龙虾吧——支持视觉识别到3D打印
|
1月前
|
存储 监控 测试技术
从检索到回答:RAG 流水线中三个被忽视的故障点
RAG系统看似运行正常,却常存在“静默故障”:检索相关但不相关、LLM自信幻觉、用户反馈未被采集。本文揭示三大缺口,并提出可落地的闭环方案——相关性门控、生成后自评估、全链路Trace追踪、用户行为信号转化,让RAG从“能答”走向“可信”。
151 6
|
11天前
|
弹性计算 人工智能 缓存
阿里云轻量应用服务器2核2G38元、2核4G9.9元起:配置解析、适用场景与选购指南
2026年阿里云轻量应用服务器抢购活动提供两大核心配置:2核2G(200M峰值带宽+40G ESSD盘)抢购价38元/年,适合个人建站与入门学习;2核4G(200M带宽+50G ESSD盘)9.9元/月或199元/年,支持OpenClaw镜像一键部署AI助理。抢购每日10:00和15:00限时开抢,仅限新用户。本文同时对比了ECS 99计划(e实例99元/年、u1实例199元/年,新购续费同价至2027年3月),建议用户根据业务规模、AI需求及长期成本综合选型。
248 14
|
12天前
|
弹性计算 人工智能 运维
阿里云服务器2核4G199元1年:轻量应用服务器抢购和云服务器u1实例对比与选购策略参考
阿里云服务器2核4G热门配置价格:轻量应用服务器2核4G(199元/年)与云服务器ECS通用算力型u1实例2核4G(199元/年)。二者虽价格相同,但定位截然不同:轻量服务器主打开箱即用,峰值带宽达200M,预装OpenClaw等AI镜像,适合新用户快速建站或AI尝鲜,但续费价格较高且需每日限时抢购;ECS u1实例则提供5M固定带宽、80G云盘,支持VPC等深度定制,企业新老用户同享,且承诺续费同价至2027年3月,长期成本更可控。本文从产品定位、适用场景、购买资格、续费政策等维度提供了以供对比与选购策略,帮助个人开发者与中小企业根据业务需求做出最优选择。
183 10
|
13天前
|
自然语言处理 JavaScript 前端开发
《Python脚本到OpenClaw技能:解锁Agent原生能力的转换指南》
本文深入探讨了将Python脚本转换为OpenClaw技能的核心逻辑与完整实践路径,指出这一过程本质是从"命令式执行"到"意图式响应"的范式转变,而非简单的代码迁移。文章重点解析了OpenClaw独特的三级渐进式披露技能架构,详细阐述了脚本解构、目录结构创建、说明文件编写、脚本适配、依赖管理及测试发布的全流程操作要点,同时分享了提升技能触发准确率、利用状态管理实现复杂交互的高级技巧与常见开发陷阱。最后,文章揭示了技能转换对提升脚本价值、参与社区贡献及个人技术变现的重要意义。
161 8

热门文章

最新文章