SpringCache一般不会单独使用,所以配合SpringDataRedis一起使用,直接上代码

当前基于 SpringBoot 2.4.5 实现

基于已经添加了spring-boot-starter-data-couchbase 还需要添加spring-boot-starter-data-redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

仔细观察org.springframework.cache.annotation.EnableCaching注解的注释,实现功能

负责注册必要的Spring组件,这些组件可以为注释驱动的缓存管理提供支持,例如CacheInterceptor以及基于代理或基于AspectJ的建议将调用@Cacheable方法时,拦截器将进入调用堆栈。如果存在JSR-107 API和Spring的JCache实现,则还将注册用于管理标准缓存注释的必要组件。 这将创建基于代理或基于AspectJ的建议,当调用以CacheResult , CachePut , CacheRemove或CacheRemoveAll注释的方法时,将拦截器编织到调用堆栈中。
必须注册CacheManager类型的Bean ,因为没有合理的默认值可以将该框架用作约定。 尽管<cache:annotation-driven>元素假定一个名为“ cacheManager”的bean,但@EnableCaching按类型搜索一个cache manager bean。 因此,高速缓存管理器bean方法的命名并不重要。
对于那些希望在@EnableCaching和要使用的确切缓存管理器bean之间建立更直接关系的@EnableCaching ,可以实现CachingConfigurer回调接口

这里有个问题,CachingConfigurer的类型为interface。即实现所有的方法,查看它的实现CachingConfigurerSupport类,具有空方法的CachingConfigurer的实现,允许子类仅覆盖其感兴趣的方法。

查看CachingConfigurer源码

public class CachingConfigurerSupport implements CachingConfigurer {

    /**
    * 返回高速缓存管理器bean,以用于注释驱动的高速缓存管理。 默认的CacheResolver将使用此缓存管理器在后台初始化。 
    * 为了更精细地管理缓存分辨率,请考虑直接设置CacheResolver, 实现必须显式声明@Bean 
    */
	@Override
	@Nullable
	public CacheManager cacheManager() {
		return null;
	}
   /**
    * 返回CacheResolver bean,用于解析注释驱动的缓存管理的常规缓存。这是指定要使用的CacheManager的替代方法,且
    * 功能更强大。如果同时设置了cacheManager()和#cacheResolver() ,则忽略缓存管理器。实现必须显式声明@Bean 
    */
	@Override
	@Nullable
	public CacheResolver cacheResolver() {
		return null;
	}
   /**
    * 返回密钥生成器Bean,以用于注释驱动的缓存管理。 实现必须显式声明@Bean 
    */
	@Override
	@Nullable
	public KeyGenerator keyGenerator() {
		return null;
	}
   /**
    * 返回CacheErrorHandler以用于处理与缓存相关的错误。默认情况下,
    * 使用org.springframework.cache.interceptor.SimpleCacheErrorHandler ,
    * 并且仅将异常抛出回客户端。实现必须显式声明@Bean 
    */
	@Override
	@Nullable
	public CacheErrorHandler errorHandler() {
		return null;
	}

}

现在也做一个CachingConfigurerSupport的实现

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 自定义实现 缓存处理器 将redis修改为默认的缓存处理器
     *
     * @return
     * @see org.springframework.cache.CacheManager
     */
    @Bean
    @Override
    public CacheManager cacheManager() {
        return super.cacheManager();
    }

    /**
     * 实现自定义的密钥
     * (如果没有自定义实现这个方法会出现什么情况,自定义生成的 redis 键 会像这样 SimpleKey [])
     *
     * @return
     * @see org.springframework.cache.interceptor.KeyGenerator
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return super.keyGenerator();
    }
}

但是这样有个问题,如何才能将缓存管理器交由Reids管理呢?

有这样的一个类org.springframework.data.redis.cache.RedisCacheManager,可以看到它的作用是

由Redis缓存支持的org.springframework.cache.CacheManager 。
默认情况下,此高速缓存管理器在首次写入时创建高速缓存。 由于Redis如何表示空数据结构,因此在Redis上看不到空缓存。
可以通过RedisCacheManager.RedisCacheManagerBuilder.withInitialCacheConfigurations(Map)来指定需要与默认配置不同的RedisCacheConfiguration缓存

所以我们需要配置一个redis的缓存管理器RedisCacheManager,观察RedisCacheManager的构造函数
刚开始可以选择使用最简单的一个构造函数,这个构造函数需要两个参数

/**
 * 创建新RedisCacheManager使用给定RedisCacheWriter和默认RedisCacheConfiguration 。
 */
public RedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
	this(cacheWriter, defaultCacheConfiguration, true);
}
  • RedisCacheWriter提供对用于缓存的Redis命令( SET, SETNX, GET, EXPIRE,... )的低级访问。 RedisCacheWriter可以由多个缓存实现共享,并负责将二进制数据写入Redis或从Redis读取二进制数据。 该实现采用可能设置的潜在缓存锁定标志。

  • RedisCacheConfiguration提供配置redis的缓存配置

RedisCacheWriter有两个静态方法,但是都需要RedisConnectionFactory

/**
 * 创建没有锁定行为的新RedisCacheWriter 
 */
static RedisCacheWriter nonLockingRedisCacheWriter(RedisConnectionFactory connectionFactory) {
	Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");
	return new DefaultRedisCacheWriter(connectionFactory);
}

/**
 * 创建有锁定行为的新RedisCacheWriter 
 */
static RedisCacheWriter lockingRedisCacheWriter(RedisConnectionFactory connectionFactory) {
	Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");
	return new DefaultRedisCacheWriter(connectionFactory, Duration.ofMillis(50));
}

又有一个新的问题RedisConnectionFactory 属于接口,需要如何配置?
RedisConnectionFactory下有一个实现JedisConnectionFactory
JedisConnectionFactory可以通过Jedis配置连接工厂

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.0</version>
</dependency>
 /**
 * Redis服务器地址
 */
@Value("${spring.redis.host}")
private String host;

/**
 * Redis服务端口
 */
@Value("${spring.redis.port}")
private int port;

/**
 * Redis服务密码
 */
@Value("${spring.redis.password}")
private String password;

/**
 * Redis服务器地址
 */
@Value("${spring.redis.database}")
private int database;

/**
 * redis 连接工厂 必须注册为 Bean
 *
 * @return
 */
@Bean
public JedisConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
    config.setDatabase(database);
    config.setPassword(password);
    return new JedisConnectionFactory(config);
}

RedisCacheConfiguration提供了默认的配置,即

RedisCacheConfiguration.defaultCacheConfig();

默认配置具有以下特点:

功能描述
密钥到期永恒
缓存空值是的
前缀缓存键是的
默认前缀[实际缓存名称]
密钥序列化器org.springframework.data.redis.serializer.StringRedisSerializer
值序列化器org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
转换服务具有default缓存密钥转换器的DefaultFormattingConversionService

现在开始配置 RedisCacheManager

/**
 * 自定义实现 缓存处理器 将redis修改为默认的缓存处理器
 *
 * @return
 * @see org.springframework.data.redis.cache.RedisCacheManager
 */
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
    return new RedisCacheManager(RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory), redisCacheConfiguration());
}

这样就可以实现将SpringCache缓存交由Redis去管理。

在这样的过程中,不断的去查询官方的文档的代码,即使看不懂实现的方式,但是这样的过程就是在过度,不能操之过急,一步一步才能继续往下面走。若有不对欢迎指出