SpringBoot3中使用Caffeine缓存组件

SpringBoot3已经把EhCache从框架中删除了,SpringBoot3默认的缓存组件为Caffeine,那么我们在SpringBoot3中如何去使用它了?

1.添加依赖

xml 复制代码
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2.配置Caffeine缓存

创建Caffeine配置类

java 复制代码
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;

@Configuration
public class CaffeineConfig {

    /**
     * 配置Caffeine缓存管理器
     */
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        // 设置缓存默认配置
        cacheManager.setCaffeine(caffeineCacheBuilder());
        // 允许动态创建缓存
        cacheManager.setAllowNullValues(false);
        return cacheManager;
    }

    /**
     * 配置Caffeine缓存属性
     * 可根据需要调整过期时间和最大缓存数量
     */
    Caffeine<Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                // 最后一次写入后经过固定时间过期
                .expireAfterWrite(60, TimeUnit.MINUTES)
                // 最大缓存条目
                .maximumSize(10000)
                // 初始缓存容量
                .initialCapacity(100)
                // 记录缓存命中率等统计信息
                .recordStats();
    }
}

3.添加工具类

添加Caffeine工具类

java 复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.util.ObjectUtils;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class CaffeineUtils {
    private static final Logger logger = LoggerFactory.getLogger(CaffeineUtils.class);

    // 获取Spring管理的缓存管理器
    private static final CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);

    // 默认缓存名称
    private static final String SYS_CACHE = "sys-cache";

    /**
     * 获取SYS_CACHE缓存
     */
    public static Object get(String key) {
        return get(SYS_CACHE, key);
    }

    /**
     * 获取SYS_CACHE缓存,带默认值
     */
    public static Object get(String key, Object defaultValue) {
        Object value = get(key);
        return value != null ? value : defaultValue;
    }

    /**
     * 写入SYS_CACHE缓存
     */
    public static void put(String key, Object value) {
        put(SYS_CACHE, key, value);
    }

    /**
     * 从SYS_CACHE缓存中移除
     */
    public static void remove(String key) {
        remove(SYS_CACHE, key);
    }


    /**
     * 从SYS_CACH缓存中移除指定key集合
     */
    public static void removeByKeys(Set<String> keys) {
        removeByKeys(SYS_CACHE, keys);
    }

    /**
     * 获取指定缓存
     */
    public static Object get(String cacheName, String key) {
        Cache cache = getCache(cacheName);
        Cache.ValueWrapper wrapper = cache.get(getKey(key));
        return wrapper != null ? wrapper.get() : null;
    }

    /**
     * 获取指定缓存,带默认值
     */
    public static Object get(String cacheName, String key, Object defaultValue) {
        Object value = get(cacheName, key);
        return value != null ? value : defaultValue;
    }

    /**
     * 写入指定缓存
     */
    public static void put(String cacheName, String key, Object value) {
        if (value != null) {
            getCache(cacheName).put(getKey(key), value);
        }
    }

    /**
     * 从指定缓存中移除
     */
    public static void remove(String cacheName, String key) {
        getCache(cacheName).evict(getKey(key));
    }

    /**
     * 清空指定缓存
     */
    public static void removeAll(String cacheName) {
        Cache cache = getCache(cacheName);
        // Caffeine不直接支持获取所有key,如需此功能需自行维护key集合
        cache.clear();
        logger.info("清理缓存:{}", cacheName);
    }

    /**
     * 从指定缓存中移除指定key集合
     */
    public static void removeByKeys(String cacheName, Set<String> keys) {
        Cache cache = getCache(cacheName);
        for (String key : keys) {
            cache.evict(getKey(key));
        }
        logger.info("清理缓存:{} => {}", cacheName, keys);
    }

    /**
     * 获取缓存键名
     */
    private static String getKey(String key) {
        return key;
    }

    /**
     * 获取缓存实例
     */
    public static Cache getCache(String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            throw new RuntimeException("当前系统中没有定义"" + cacheName + ""这个缓存。");
        }
        return cache;
    }

    /**
     * 获取所有缓存名称
     */
    public static String[] getCacheNames() {
        return cacheManager.getCacheNames().toArray(new String[0]);
    }
}

4.注意事项

  1. Caffeine 不直接支持获取缓存中的所有 key(getKeys()方法),如果需要此功能,需自行维护 key 集合
  2. 缓存配置(过期时间等)可以针对不同缓存名称单独配置,需要额外扩展
  3. 移除了allowNullValues的支持,建议缓存中不存储 null 值

5.性能优势

  1. Caffeine 基于 Java 8,使用更高效的算法(W-TinyLFU)
  2. 平均访问时间更短,内存占用更优
  3. 支持异步加载等高级特性(如需可扩展实现)
相关推荐
2501_933923254 分钟前
Spring Bean作用域揭秘:单例、原型、请求与会话的区别
java·后端·spring·java-ee
学编程就要猛22 分钟前
基于Spring AI 的智能聊天机器人
java·spring ai·chat robot
修炼室24 分钟前
Java开发工程师笔试经验贴【高频知识】
java
木井巳37 分钟前
【记忆化搜索】最长递增子序列
java·算法·leetcode·深度优先·剪枝·推荐算法
杨杨杨大侠44 分钟前
知识库已经有了,Java 程序员还要做什么?Spring AI RAG 实战
java·openai·ai编程
伊信1 小时前
Spring AI 基础学习与应用
java·后端
夜郎king1 小时前
基于 Java + Playwright 实现网站自动访问与数据采集(以腾讯云开发者社区为例)
java·playwright·网页数据获取
Anastasiozzzz1 小时前
重新定义 Agent 基建:Redis 在现代 AI 与智能体系统中的工程实践
java·人工智能·redis·ai
careathers1 小时前
【数据结构】队列
java·数据结构
步行cgn1 小时前
Spring 通过 factory-method 实例化 Bean 详解与常见错误排查
java·后端