学科分类
目录
Spring Boot开发

Spring Boot缓存注解介绍

在6.1.2小节中,通过使用@EnableCaching、@Cacheable注解实现了Spring Boot默认的基于注解的缓存管理,除此之外,还有更多的缓存注解以及注解属性可以配置优化缓存管理。下面,针对Spring Boot中的缓存注解及相关属性进行详细讲解。

1.@EnableCaching注解

@EnableCaching是由Spring框架提供的,Spring Boot框架对该注解进行了继承,该注解需要配置在类上(在Spring Boot中,通常配置在项目启动类上),用于开启基于注解的缓存支持。

2.@Cacheable注解

@Cacheable注解也是由Spring框架提供的,可以作用于类或方法(通常用在数据查询方法上),用于对方法结果进行缓存存储。@Cacheable注解的执行顺序是,先进行缓存查询,如果为空则进行方法查询,并将结果进行缓存;如果缓存中有数据,不进行方法查询,而是直接使用缓存数据。

@Cacheable注解提供了多个属性,用于对缓存存储进行相关配置,具体属性及说明如表1所示。

表1 @Cacheable注解属性及说明

属性名 说明
value/cacheNames 指定缓存空间的名称,必配属性。这两个属性二选一使用
key 指定缓存数据的key,默认使用方法参数值,可以使用SpEL表达式
keyGenerator 指定缓存数据的key的生成器,与key属性二选一使用
cacheManager 指定缓存管理器
cacheResolver 指定缓存解析器,与cacheManager属性二选一使用
condition 指定在符合某条件下,进行数据缓存
unless 指定在符合某条件下,不进行数据缓存
sync 指定是否使用异步缓存。默认false

下面,针对@Cacheable注解的属性进行具体讲解。

(1)value/cacheNames属性

value和cacheNames属性作用相同,用于指定缓存的名称空间,可以同时指定多个名称空间(例如@Cacheable(cacheNames = {"comment1","comment2"})),这两个属于必配选项,且要二选一使用。如果@Cacheable注解只配置value(或者cacheNames)的一个属性,那么这两个属性名可以省略,例如@Cacheable("comment")指定了缓存的名称空间为comment。

(2)key属性

key属性作用是指定缓存数据对应的唯一标识,默认使用注解标记的方法参数值,也可以使用SpEL表达式。缓存数据的本质是Map类型数据,key用于指定唯一的标识,value用于指定缓存的数据。

进行数据缓存时,如果没有指定key属性,Spring Boot默认配置类SimpleKeyGenerator中的generateKey(Object... params)方法会根据方法参数生成key值。对于一个参数的方法,其key是默认参数值;对于没有参数的方法,其key是默认创建的空参SimpleKey[]对象;对于有多个参数的方法,其key是默认创建的带参SimpleKey[params1, [params2,..]对象。

除了使用默认key属性值外,还可以手动指定key属性值,或者是使用Spring框架提供的SpEL表达式。关于缓存中支持的SpEL表达式及说明如表2所示。

表2 Cache缓存支持的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 执行上下文 当前被调用的方法参数,可以用#参数名或者#a0、#p0的形式(0代表参数索引,从0开始) #comment_id、#a0、#p0
result 执行上下文 当前方法执行后的返回结果 #result

(3)keyGenerator属性

keyGenerator属性与key属性本质作用相同,都是用于指定缓存数据的key,只不过keyGenerator属性指定的不是具体的key值,而是key值的生成器规则,由其中指定的生成器生成具体的key。使用时,keyGenerator属性与key属性要二者选一。关于自定义key值生成器的定义,可以参考Spring Boot默认配置类SimpleKeyGenerator的定义方式,这里不做具体说明了。

(4)cacheManager/cacheResolver属性

cacheManager和cacheResolver属性分别用于指定缓存管理器和缓存解析器,这两个属性也是二选一使用,默认情况不需要配置,如果存在多个缓存管理器(例如Redis、Ehcache等),可以使用这两个属性分别指定。

(5)condition属性

condition属性用于对数据进行有条件的选择性存储,只有当指定条件为true才会对查询结果进行缓存,可以使用SpEL表达式指定属性值。例如@Cacheable(cacheNames = "comment",condition = "#comment_id>10")表示方法参数comment_id的值大于10才会对结果数据进行缓存。

(6)unless属性

unless属性的作用与condition属性相反,当指定的条件为true,方法的返回值不会被缓存,也可以使用SpEL表达式指定。例如@Cacheable(cacheNames = "comment",unless = "#result==null")表示只有查询结果不为空才会对结果数据进行缓存存储。

(7)sync属性

sync属性表示数据缓存过程中是否使用异步模式,默认值为false,通常不会使用该属性。

3.@CachePut注解

@CachePut注解是由Spring框架提供的,可以作用于类或方法(通常用在数据更新方法上),该注解的作用是更新缓存数据。@CachePut注解的执行顺序是,先进行方法调用,然后将方法结果更新到缓存中。

@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。

4.@CacheEvict注解

@CacheEvict注解是由Spring框架提供的,可以作用于类或方法(通常用在数据删除方法上),该注解的作用是删除缓存数据。@CacheEvict注解的默认执行顺序是,先进行方法调用,然后将缓存进行清除。

@CacheEvict注解也提供了多个属性,这些属性与@Cacheable注解的属性基本相同,除此之外,还额外提供了两个特殊属性allEntries和beforeInvocation。其中:

(1)allEntries属性

allEntries属性表示是否清除指定缓存空间中的所有缓存数据,默认值为false(即默认只删除指定key对应的缓存数据)。例如@CacheEvict(cacheNames = "comment",allEntries = true)表示方法执行后会删除缓存空间comment中所有的数据。

(2)beforeInvocation属性

beforeInvocation属性表示是否在方法执行之前进行缓存清除,默认值为false(即默认在执行方法后再进行缓存清除)。例如@CacheEvict(cacheNames = "comment",beforeInvocation = true)表示会在方法执行之前进行缓存清除。

需要注意的是,如果将@CacheEvict注解的beforeInvocation属性设置为true,会存在一定的弊端。例如在进行数据删除的方法中发生了异常,这会导致实际数据并没有被删除,但是缓存数据却被提前清除了。

5.@Caching注解

@Caching注解用于针对复杂规则的数据缓存管理,可以作用于类或方法,在@Caching注解内部包含有Cacheable、put和evict三个属性,分别对应于@Cacheable、@CachePut和@CacheEvict三个注解,示例代码如下。

@Caching(cacheable={@Cacheable(cacheNames ="comment",key = "#id")},
        put = {@CachePut(cacheNames = "comment",key = "#result.author")})
public Comment getComment(int comment_id){
    return commentRepository.findById(comment_id).get();
}

上述代码中,getComment()方法使用了@Caching注解,并使用cacheable和put两个属性嵌套引入了@Cacheable 和@CachePut 两个注解,分别以id、和author为缓存key值,以查询结果Comment为缓存value值进行缓存管理。

6.@CacheConfig注解

@CacheConfig注解使用在类上,主要用于统筹管理类中所有使用@Cacheable、@CachePut和@CacheEvict注解标注方法中的公共属性,这些公共属性包括有cacheNames、keyGenerator、cacheManager和cacheResolver,示例代码如下。

@CacheConfig(cacheNames = "comment")
@Service
public class CommentService {
    @Autowired
    private CommentRepository commentRepository;
    @Cacheable
    public Comment findById(int comment_id){
        Comment comment = commentRepository.findById(comment_id).get();
        return comment;
    }
    ...
}

上述代码中,CommentService类上标注了@CacheConfig注解,同时使用cacheNames属性将缓存空间统一设置为comment,这样在该类中所有方法上使用缓存注解时可以省略相应的cacheNames属性。

需要说明的是,如果在类上使用了@CacheConfig注解定义了某个属性(例如cacheNames),同时又在该类方法中使用缓存注解定义了相同的属性,那么该属性值会使用“就近原则”选择以方法上注解中的属性值为准。

点击此处
隐藏目录