Springboot中缓存推荐使用注解方式
参考:https://blog.csdn.net/wujiaqi0921/article/details/79123873
摘要
1.@Cacheable
@Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。
Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。
@Cacheable可以指定三个属性,value、key和condition。
- value:缓存的名称,在 spring 配置文件中定义,必须指定至少一个。如@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}
- key:缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。如@Cacheable(value=”testcache”,key=”#userName”)
- condition:缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存。如@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
注:除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。
- @Cacheable(cacheResolver=”MyCacheResolver”)执行缓存解析器
- @Cacheable(cacheManager=”“)执行缓存管理器,默认使用currentMapCacheManager
- @Cacheable(cacheNames=”“)指定缓存的名称
- @Cacheable(keyGenerator=”“)在未指定key时指定缓存key值的生成器
- @Cacheable(unless=”“) 过滤不需要缓存的值,支持spEl表达式。
public User findById(String id) {
System.out.println("执行数据库查询方法");
return userDao.findById(id);
}
2.@CachePut
在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。
@CachePut(value = "user", key = "#id", condition = "#id != '321'")
public User findById(String id) {
System.out.println("执行数据库查询方法");
return userDao.findById(id);
}
3.@CacheEvict
@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。
下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。
- allEntries:是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存。如:@CachEvict(value=”testcache”,allEntries=true)
- beforeInvocation:是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。如:@CachEvict(value=”testcache”,beforeInvocation=true)
allEntries指定为true时,则会清楚所有缓存。
其他参数和@Cacheable相同
@CacheEvict(value = "user", key = "#id")
public void deleteUserById(String id) {
}
4.@Caching
@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。使用如下
@Caching(cacheable = {@Cacheable(value = "user", key = "#id", condition = "#id != '123'"),
@Cacheable(value = "user", key = "#id", condition = "#id != '321'")}
)
public User findById(String id) {
System.out.println("执行数据库查询方法");
return userDao.findById(id);
}
在上面我们没有没使用指定的缓存解析器,以及key生成器。那么我们如何来实现自己的解析器,缓存管理类或者key生成器呢?我们可以通过实现org.springframework.cache.interceptor.KeyGenerator接口实现自己想要的主键生成器,通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器。在这里就不进行代码展示了。
这里还需要提到@CacheConfig用于指定类全局配置。
另外,代码行级使用,我封装了个工具类
功能随用随增加,先提供基本的常用方法
package com.qdzklt.rdm.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
/**
* 缓存操作工具类
*/
@Component
public class CacheUtil {
private static RedisTemplate redisTemplate;
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate) {
CacheUtil.redisTemplate = redisTemplate;
}
/**
* 获得RedisTemplate
*
* @return RedisTemplate
*/
public static RedisTemplate getRedisTemplate() {
return redisTemplate;
}
/**
* 是否包含某个key
*
* @param key key
* @return booble
*/
public static Boolean hasKey(Object key) {
return redisTemplate.hasKey(key);
}
/**
* 添加或更新
*
* @param key 键
* @param value 值
*/
public static void set(Object key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 获取
*
* @param key 键
*/
public static Object get(Object key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 删除
*
* @param key 键
*/
public static void delete(Object key) {
redisTemplate.delete(key);
}
/**
* 删除
*
* @param keys 键集合
*/
public static void delete(Collection keys) {
redisTemplate.delete(keys);
}
}