Spring Cache 介绍
# 一、简介
从 3.1 版开始,Spring 框架提供了对将缓存透明添加到现有 Spring 应用程序的支持。与transaction (opens new window)支持类似,缓存抽象允许一致使用各种缓存解决方案,而对代码的影响最小。在 Spring-Context
包中定义了 org.springframework.cache.Cache
和 org.springframework.cache.CacheManager
两个接口来统一不同的缓存技术。Cache 接口包含缓存的常用操作:增加、删除、读取等。CacheManager 是 Spring 各种缓存的抽象接口。 Spring 支持的常用 CacheManager 如下:
CacheManager | 描述 |
---|---|
SimpleCacheManager | 使用简单的 Collection 来存储缓存 |
ConcurrentMapCacheManager | 使用 java.util.ConcurrentHashMap 来实现缓存 |
NoOpCacheManager | 仅测试用,不会实际存储缓存 |
EhCacheCacheManger | 使用EhCache作为缓存技术。EhCache 是一个纯 Java 的进程内缓存框架,特点快速、精干,是 Hibernate 中默认的 CacheProvider,也是 Java 领域应用最为广泛的缓存 |
JCacheCacheManager | 支持JCache(JSR-107)标准的实现作为缓存技术 |
CaffeineCacheManager | 使用 Caffeine 作为缓存技术。用于取代 Guava 缓存技术。 |
RedisCacheManager | 使用Redis作为缓存技术 |
HazelcastCacheManager | 使用Hazelcast作为缓存技术 |
CompositeCacheManager | 用于组合 CacheManager,可以从多个 CacheManager 中轮询得到相应的缓存 |
# 二、基于声明式注解的缓存
对于缓存声明,Spring提供了一组 Java 注解:
@Cacheable
: 触发添加缓存@CacheEvict
: 触发缓存清除@CachePut
:在不影响方法执行的情况下更新缓存。@Caching
:重新组合要在一个方法上应用的多个缓存操作。@CacheConfig
:在类级别共享一些与缓存有关的常见设置。
# 1、@EnableCaching 注解
开启缓存功能
# 2、@CacheConfig 注解
可以在类级别上标注一些共用的缓存属性。(所有方法共享,@since 4.1)
# 3、@Cacheable 注解
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。
属性 | 解释 |
---|---|
value | 缓存名,必填,用于指定缓存存储的集合名。 |
cacheNames | 与 value 差不多,二选一即可 |
key | 可选属性,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0") :使用函数第一个参数作为缓存的key值 |
keyGenerator | key的生成器。非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator 接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的 |
cacheManager | 指定缓存管理器 |
cacheResolver | 指定获取解析器,用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver 接口来实现自己的缓存解析器,并用该参数指定。 |
condition | 缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:·、@Cacheable(key = "#p0", condition = "#p0.length() < 3") ,表示只有当第一个参数的长度小于3的时候才会被缓存 |
unless | 另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。 |
sync | 是否使用异步模式,默认为false |
# 4、@CachePut 注解
主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable
不同的是,它每次都会触发真实方法的调用 。简单来说就是用户更新缓存数据。但需要注意的是该注解的 value
和 key
必须与要更新的缓存相同,也就是与@Cacheable
相同。
# 5、@CacheEvict 注解
通常用在删除方法上,用来从缓存中移除相应数据。除了同@Cacheable一样的参数之外,它还有下面两个参数:
属性 | 解释 |
---|---|
allEntries | 非必需,默认为false。当为true时,会移除所有数据。如:@CachEvict(value="users",allEntries=true) |
beforeInvocation | 非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。 如:@CachEvict(value="users",beforeInvocation=true) |
# 6、@Caching 注解
该注解可以实现同一个方法上同时使用多种注解。可从其源码看出:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
2
3
4
5
6
7
8
9
10
11
12
13
# 三、SpEL上下文数据
# 1、SpEL
名称 | 位置 | 描述 | 示例 |
---|---|---|---|
methodName | root对象 | 当前被调用的方法名 | #root.methodname |
method | root对象 | 当前被调用的方法 | #root.method.name |
target | root对象 | 当前被调用的目标对象实例 | #root.target |
targetClass | root对象 | 当前被调用的目标对象的类 | #root.targetClass |
args | root对象 | 当前被调用的方法的参数列表 | #root.args[0] |
caches | root对象 | 当前方法调用使用的缓存列表 | #root.caches[0].name |
Argument Name | 执行上下文 | 当前被调用的方法的参数,如findUser(User user),可以通过#user.id获得参数 | #user.id |
result | 执行上下文 | 方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false) | #result |
注意:
当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。 如
@Cacheable(key = "targetClass + methodName +#p0")
使用方法参数时我们可以直接使用#参数名
或者#p参数index
。 如:
@Cacheable(value="users", key="#id")
@Cacheable(value="users", key="#p0")
2
# 2 、SpEL提供了多种运算符
类型 | 运算符 |
---|---|
关系 | <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne |
算术 | +,- ,* ,/,%,^ |
逻辑 | &&,||,!,and,or,not,between,instanceof |
条件 | ?: (ternary),?: (elvis) |
正则表达式 | matches |
其他类型 | ?.,?[…],![…],^[…],$[…] |