spring cache 支持多结构的 Redis 缓存管理器

需求背景:spring cache 使用多级缓存,缓存实现方式用redis时,默认存储的结构是string,结果,但项目中需要使用其他结果,于是想到自己定义一个实现类,然后根据类型进行切换不同的实现方式,于是乎有了下面多结构缓存管理器,核心方法是createRedisCache

复制代码
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import java.util.Map;
import java.util.Objects;

/**
 * 支持多结构的 Redis 缓存管理器
 * 可根据缓存名前缀自动选择缓存结构(Hash/ZSet/普通字符串)
 */
public class StructRedisCacheManager extends RedisCacheManager {

    // 缓存结构类型枚举
    public enum CacheStructType {
        HASH,   // Hash 结构
        ZSET,   // ZSet 结构
        STRING  // 普通字符串结构(默认)
    }

    // 结构前缀(用于标识缓存类型,例如 "hash:userCache" 表示 Hash 结构)
    private static final String HASH_PREFIX = "hash:";
    private static final String ZSET_PREFIX = "zset:";

    private final RedisConnectionFactory connectionFactory;
    // 各结构的默认配置(是否允许覆盖/重复)
    private final boolean hashAllowOverwrite;  // Hash 是否允许覆盖
    private final boolean zsetAllowDuplicate; // ZSet 是否允许重复元素

    public StructRedisCacheManager(
            RedisCacheWriter cacheWriter,
            RedisCacheConfiguration defaultCacheConfig,
            RedisConnectionFactory connectionFactory,
            boolean hashAllowOverwrite,
            boolean zsetAllowDuplicate
    ) {
        super(cacheWriter, defaultCacheConfig);
        this.connectionFactory = connectionFactory;
        this.hashAllowOverwrite = hashAllowOverwrite;
        this.zsetAllowDuplicate = zsetAllowDuplicate;
    }

    /**
     * 重载构造器(支持自定义缓存配置)
     */
    public StructRedisCacheManager(
            RedisCacheWriter cacheWriter,
            RedisCacheConfiguration defaultCacheConfig,
            Map<String, RedisCacheConfiguration> initialCacheConfigurations,
            RedisConnectionFactory connectionFactory,
            boolean hashAllowOverwrite,
            boolean zsetAllowDuplicate
    ) {
        super(cacheWriter, defaultCacheConfig, initialCacheConfigurations);
        this.connectionFactory = connectionFactory;
        this.hashAllowOverwrite = hashAllowOverwrite;
        this.zsetAllowDuplicate = zsetAllowDuplicate;
    }

    /**
     * 核心:根据缓存名选择对应的缓存结构实现
     */
    @Override
    protected RedisCache createRedisCache(String cacheName, RedisCacheConfiguration config) {
        // 解析缓存结构类型
        CacheStructType structType = parseStructType(cacheName);
        // 提取业务缓存名(去除结构前缀)
        String bizName = extractBizName(cacheName, structType);

        // 根据类型创建对应缓存实例
        switch (structType) {
            case HASH:
                // 创建 Hash 结构缓存
                return new HashRedisCache(
                        bizName,
                        getCacheWriter(),
                        config != null ? config : getDefaultCacheConfiguration(),
                        connectionFactory,
                        hashAllowOverwrite
                );
            case ZSET:
                // 创建 ZSet 结构缓存
                return new ZSetRedisCache(
                        bizName,
                        getCacheWriter(),
                        config != null ? config : getDefaultCacheConfiguration(),
                        connectionFactory,
                        zsetAllowDuplicate
                );
            default:
                // 默认使用普通字符串缓存(Spring 原生实现)
                return super.createRedisCache(bizName, config);
        }
    }

    /**
     * 解析缓存名对应的结构类型(通过前缀判断)
     */
    private CacheStructType parseStructType(String cacheName) {
        if (cacheName.startsWith(HASH_PREFIX)) {
            return CacheStructType.HASH;
        } else if (cacheName.startsWith(ZSET_PREFIX)) {
            return CacheStructType.ZSET;
        } else {
            return CacheStructType.STRING;
        }
    }

    /**
     * 提取业务缓存名(去除结构前缀)
     */
    private String extractBizName(String cacheName, CacheStructType structType) {
        switch (structType) {
            case HASH:
                return cacheName.substring(HASH_PREFIX.length());
            case ZSET:
                return cacheName.substring(ZSET_PREFIX.length());
            default:
                return cacheName;
        }
    }
}
相关推荐
努力努力再努力wz33 分钟前
【Redis入门系列】:Redis 内部编码机制与 String 深度解析:SDS 底层实现、三种编码与核心命令详解
c语言·开发语言·数据结构·数据库·c++·redis·缓存
Mahir0838 分钟前
Spring 全家桶常见注解全解:从入门到精通
java·后端·spring·面试·常见注解
执笔论英雄43 分钟前
GPU内存架构-DSMEM与L2
java·spring·架构
晚烛1 小时前
CANN 数据增强 on NPU:训练数据增强的 NPU 加速实战
人工智能·python·深度学习·缓存·数据挖掘
憧憬成为java架构高手的小白1 小时前
苍穹外卖项目-day02
java·spring
IT_Octopus10 小时前
Spring Boot 实战:@PostConstruct + Caffeine 缓存初始化与定时刷新
spring boot·后端·缓存
Java面试题总结11 小时前
java高频面试题(2026最新)
java·开发语言·jvm·数据库·spring·缓存
牧羊狼的狼12 小时前
浅谈电商下单微服务流程
spring·spring cloud·微服务
西安邮电大学13 小时前
SpringBean完整生命周期
java·spring
范什么特西13 小时前
Spring 动态代理 静态代理
java·后端·spring