SpringBoot中Redis缓存注解
Spring框架中所有的注解都是通过AOP的原理实现的,即Spring框架为我们创建代理对象,代理对象去实现注解的功能。所以当一个支持缓存的方法,在对象内部被调用的时候,是不会触发缓存功能的,因为当前类方法调用当前类方法使用的是this.调用,也就是当前对象,而不是代理对象,增强没有上生效。
@Cacheable、@Cacheput、@CacheEvict 是 Spring3.1 版本以后对缓存支持的注解。这些注解作用在方法上。使用了Spring AOP的思想。@Cacheable、@Cacheput、@CacheEvict 这些注解不是专门针对 Redis 的,而是针对本地缓存的。但是在 SpringBoot 框架中,可以使用这些注解配合 Redis 进行使用。
@Cacheable
使用存在查询的方法上
此注解标记可以使用在一个方法上也可以使用在一个类上。标记在方法上表示该方法是支持缓存的,标记在类上表示该类中所有的方法都是支持缓存的。
该注解的作用原理: 首先在执行查询方法之前,会先查询缓存,如果在缓存中查询到想要的数据就会直接返回,不会再执行此方法;如果在缓存中没有查到就会查询数据库,并且将查询结果作为该方法的返回值返回。Spring Cache会将该方法的返回值缓存起来。保证下次利用同样的参数执行该方法的时候,直接从缓存中获取结果,而不需要执行此方法。
在缓存方法的返回值的时候,是以键值对的形式存储到缓存中。值就是该方法的返回结果。键需要自己指定,spring中支持两种生成key的策略。EL表达式和自定义。在EL表达式中详细说明。
运行流程
- 方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
- 去Cache中查找缓存的内容,使用一个key,默认就是方法的参数,key是按照某种策略生成的,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key。
- SimpleKeyGenerator生成key的默认策略:
- 如果没有参数;key=new SimpleKey();
- 如果有一个参数:key=参数的值
- 如果有多个参数:key=new SimpleKey(params);
- 没有查到缓存就调用目标方法。
- 将目标方法返回的结果,放进缓存中。 @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据。
@Cacheable注解中可以定义三个属性@Cacheable(value="",key="",condition="",unless="")
- cacheNames/value: 指定缓存的名称,该属性必须指定。表示当前方法的返回值会被存储到哪个缓存上。也可以指定多个。
- key: 指定缓存结果对应的key。支持SpEL表达式的方式赋值。可以不指定,不指定的时候使用默认值,默认值就是将方法的所有参数进行组合,作为key。
Spring还提供了root对象来生成key,通过root对象可以获取到一下信息:
属性名称 | 描述 | 示例 |
methodName | 当前方法名 | #root.methodName |
method | 当前方法 | #root.method.name |
target | 当前被调用对象 | #root.target |
targetClass | 当前被调用对象的class | #root.targetClass |
args | 当前方法参数组成的数组 | #root.args[0] |
caches | 当前被调用的方法使用的Cache | #root.caches[0].name |
- keyGenerator: key的生成器,可以自己指定key的生成器的组件id。 默认生成器: SimpleKeyGenerator
- key 和 keyGenerator 属性两者互斥,二选一使用
- cacheManager: 指定缓存管理器,或者 cacheResolver 指定获取解析器
- condition: 表示缓存条件,不设置的时候,缓存所有的返回结果。设置的时候,通过SpEL表达式指定,只有当表达式为true的时候,缓存才会被触发,将返回结果缓存。
- 例如: condition = "#a0>1"表示第一个参数的值>1的时候才进行缓存
@Cacheable(cacheNames = "sum", key = "#root.args[0]", condition = "#id!=null", unless = "#result==null")
public Map<String, ResData> selectSum(Long id) {
// 查询,并将结果返回
return sumDao.querySum(id);
}
- unless: 除…之外。也表示缓存条件,不设置的时候,缓存所有的返回结果。设置的时候,通过SpEL表达式指定,只有当表达式为false的时候,缓存才会被触发,将返回结果缓存。
@Cacheable(cacheNames = "sum", key = "#root.args[0]", condition = "#id!=null", unless = "#result==null")
public Map<String, ResData> selectSum(Long id) {
// 查询,并将结果返回
return sumDao.querySum(id);
}
注意:condition & unless 区别:
condition用方法的参数作为判断条件,也就是说根据犯法的参数判断是否信息存放到缓存中。而unless是将方法的返回值作为判断条件,也就是说根据方法的返回值判断,是否将信息存放到缓存中。
- sync: 是否使用异步模式
@Cacheput
使用在添加和修改的方法上
@Cacheput 标注的方法在执行之前不会去查询缓存
,每次都会执行该方法,在该方法执行完后,将该方法的返回值以键值对的形式保存到缓存中。和 @Cacheable 不同的是,它每次都会触发真实方法的调用
其属性和@Cacheable属性一样。
value属性,必须指定。
@CacheEvict
用在清除缓存到方法上。
可以标记在类上,也可以标记在方法上,标记在雷伤的时候表示该类中所有的方法执行都会触发清除缓存的操作
该注解可以定义的属性有:value、key、condition、allEntries 和 beforeInvocation。
- value: 指定缓存的名称
- key: 指定要清除的缓存的key。不指定将会使用默认生成策略生成的key,默认生成策略就是将方法中所有参数拼接为key
- condition: 指定触发清除缓存操作的条件。
- allEntries: 该属性是一个boolean类型的,表示是否清除缓存中的所有的数据。默认的是false,当指定为true的时候,将会忽略指定的key。会清除缓存中所有的数据。
- beforeInvocation: 清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@CacheConfig
标记在类上。有时候一个类中可能会有多个缓存操作,而这些缓存使用的可能是同一个缓存,这个时候就可以使用@CacheConfig来配置缓存的名称。
所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置。如果你在你的方法写别的名字,那么依然以方法的名字为准。
@EnableCaching
springboot启动器上添加此注解,表示开始缓存功能,否则缓存不生效
参考网址
- SpringBoot中使用Redis
- @Cacheable缓存注解
- spring.cache官方文档
- springboot-redisson 源码