文档:https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/integration.html#cache
Spring为我们提供了一组缓存的高级接口, 是基于注解的声明式缓存, 非常方便,主要的注解有:
@Cacheable, @CacheEvict, @CachePut, @Caching, @CacheConfig。
示例配置
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,
RedisCacheConfiguration redisCacheConfiguration) {
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
}
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
RedisSerializationContext.SerializationPair keySerializationPair
= RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer());
RedisSerializationContext.SerializationPair> valueSerializationPair
= RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer());
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMillis(expireTime))
.serializeKeysWith(keySerializationPair)
.serializeValuesWith(valueSerializationPair)
.disableCachingNullValues();
}
}
作用于方法,调用方法时,会将结果缓存到配置好的缓存中,下次调用方法时直接返回缓存数据。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {
@AliasFor("cacheNames")
String[] value() default {};
@AliasFor("value")
String[] cacheNames() default {};
String key() default "";
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
String condition() default "";
String unless() default "";
boolean sync() default false;
}
Cacheable是一个非常重要的注解, 它的主要作用是调用某一个方法时,先根据condition条件确定是否使用缓存,然后根据key去名称为cacheName的缓存块中查找缓存,如果找到直接返回缓存结果,如果没有找到就执行方法体,然后根据unless判断是否将结果放入缓存。
现在来看里面重要的参数:
缓存块名称, 缓存块里可放多组key-value, 可以使用@CacheEvict清除整个缓存块的数据。
@Cacheable可以有多个缓存块,每个缓存块都会执行接下来的可能缓存操作。
缓存key,是SpEL表达式,默认是"",表示所有方法的参数都参与计算key(实际上是所有参数进行hashcode),如果方法没有参数,那就使用SimpleKey.EMPTY作为key, 和keyGenerator互斥。
表达式中可以使用特定参数:
示例
@Cacheable(cacheNames = "template")
public Template getById0(Long templateId) {
//...
}
@Cacheable(cacheNames = "template", key = "#root.args[0]")
public Template getById1(Long templateId) {
//...
}
@Cacheable(cacheNames = "template", key = "#p0")
public Template getById0(Long templateId) {
//...
}
启用缓存条件, 是SpEL表达式, 如果condition不满足, 那@Cacheable就不生效。
condition的测试可以使用和key一样的特定参数。
特别要注意的是condition是在进入方法前测试的。
缓存返回的结果,除非…
意思是满足条件的话,就不缓存了,和condition是相反的意思,其实我觉得叫uncacheCondition更合适。
unless的测试可以使用和key一样的特定参数,然后它还多了一个#result代表返回的结果。
特别要注意的是unless是在方法返回后测试的。
特别要注意的是,如果condition不满足,那么unless就不会再测试了,因为缓存都不起作用了。
例(如果结果返回空就不缓存)
@Cacheable(cacheNames = "template", key = "#p0", unless="#result==null")
public Template getById0(Long templateId) {
//...
}
自定义key生成器, 和上面的key互斥, 需要实现以下接口:
@FunctionalInterface
public interface KeyGenerator {
Object generate(Object target, Method method, Object... params);
}
默认的缓存管理器是容器内的CacheManager bean, 但是我们可以使用cacheManager或者cacheResolver获取特定的缓存块cache.
缓存管理器bean, 和cacheResolver互斥
需要实现以下接口:
public interface CacheManager {
/**
* 返回指定缓存名的缓存块
*/
@Nullable
Cache getCache(String name);
/**
* 返回缓存块名列表
*/
Collection getCacheNames();
}
cache路由,返回相应的缓存块,和cacheManager互斥。
指示在多线程访问key的缓存时是否进行同步, 默认为false, 如果同步会有多种限制,一般不需要(除非 缓存不支持并发读取同一个key)。
注意: 方法返回为Optional的时候, 只有有值的时候才会被缓存, 而#result是指向里面的值,而不是整个Optional.
清除缓存,通常在方法执行后清除
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheEvict {
@AliasFor("cacheNames")
String[] value() default {};
@AliasFor("value")
String[] cacheNames() default {};
String key() default "";
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
String condition() default "";
boolean allEntries() default false;
boolean beforeInvocation() default false;
}
参数含义和@Cache基本一样,不同的是它要清除缓存。
allEntries: 缓存块中的缓存是否要全部移除,默认为false
beforeInvocation:是否在方法执行前删除缓存,默认为false\
更新/放置缓存, 参数和@Cacheable一样。
在一个方法上使用多个缓存注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
Cacheable[] cacheable() default {}; // @Cache列表
CachePut[] put() default {}; //@CachePut列表
CacheEvict[] evict() default {}; //@CacheEvict列表
}
以上注解全部是基于方法的, 而@CacheConfig是基于类的缓存配置
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheConfig {
String[] cacheNames() default {};
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
}