缓存注解
# 缓存注解
JSR107(使用缓存规范)定义了5个核心接口,CachingProvider、CacheManager、Cache、Entry和Expiry。
一个应用里可以有多个缓存提供者(CachingProvider),一个缓存提供者可以获取到多个缓存管理器(CacheManager),一个缓存管理器管理着不同的缓存(Cache),缓存中是一个个的缓存键值对(Entry),每个entry都有一个有效期(Expiry)。
- img: https://bitouyun.com/images/redis/cache.png
link: https://bitouyun.com/images/redis/cache.png
name: JSR107
2
3
# 配置
- 开启缓存注解
@EnableCaching : 在启动类或配置类上使用此注解,允许使用注解方式进行缓存操作。 - 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2
3
4
# 常用缓存注解
# @Cacheable
通常用在查询方法上,加上该注解后,调用时如果缓存存在,则直接从缓存中获取数据,否则会执行该方法并将结果存入缓存。
@Service
public class UserServiceImpl implements UserService{
@Override
@Cacheable(value = "users", key = "#root.methodName", unless = "#result == null or #result.size()==0")
public List<UserDTO> findAllUser() {
log.debug("查询所有用户");
return this.userMapper.toDto(this.userRepository.selectList(null));
}
}
2
3
4
5
6
7
8
9
参数说明
value / cacheNames : 缓存名称,通过这个值来区分不同缓存的配置。
key : 缓存key,可以使用 #root对象、 '固定值'、 SPEL表达式(#user.id等)。
keyGenerator: 指定key生成器。
unless : 不缓存条件,为true时不缓存,结果为null或列表大小为0时不缓存数据。
cacheManager : 指定缓存管理器,比如默认使用的是RedisCacheManager,可以单独使用其它的缓存管理器。
cacheResolver : 指定此注解的缓存解析器,和缓存管理器互斥。
condition : 设置使用缓存条件,使用SPEL表达式解析,如果表达式返回false,则这次执行不走缓存。
sync : 采用同步的方式,默认false。
# @CachePut
通常用在新增、更新方法上,加上该注解后,每次都会执行该方法并将结果存入缓存中。即先调用方法,如果缓存中存在该数据,则更新为方法返回值,如果不存在,则把方法的结果添加到缓存中。
该方法不会影响方法的执行,即使缓存更新失败,方法也正常执行,需要确保方法执行和缓存更新结果一致。
一般情况下使用 @CacheEvict。
@Service
public class UserServiceImpl implements UserService{
// 用在新增、更新方法上,会新增或更新key为userid的数据(新增参数user id为空时会报错).
@Override
@CachePut(value = "users", key = "#user.id") // 不会更新users::findAllUser缓存数据
public User saveUser(User user) {
return userRepository.save(user);
}
}
2
3
4
5
6
7
8
9
# @CacheEvict
通常用在更新、删除方法上,加上该注解后,会移除指定的缓存。
@Service
public class UserServiceImpl implements UserService{
// 添加用户
// key:删除指定key的键值(users::findAllUser)
@Override
@CacheEvict(value = "users", key = "'findAllUser'") // allEntries = false(默认),设置为true则key将无效
public UserDTO create(UserDTO userDTO) {
log.debug("添加用户:{}", userDTO);
User user = this.userMapper.toEntity(userDTO);
this.userRepository.insert(user);
return this.userMapper.toDto(user);
}
// 删除用户
// allEntries = true 删除全部users缓存数据
@Override
@CacheEvict(value = "users", allEntries = true)
public void deleteUser(List<Integer> ids) {
log.debug("删除用户:{}", ids);
ids.forEach(id -> this.userRepository.deleteById(id));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
其它参数
beforeInvocation = true 先删除缓存,在执行方法,不管是否异常,缓存被清空。
beforeInvocation = false(默认) 出现异常不删除缓存。
# @Caching
将多个注解组合在一起,可以同时使用多个注解,用于定义复杂的缓存规则。
# @CacheConfig
通常用在类上,抽取缓存的公共配置,用于配置缓存公共参数,如缓存管理器、缓存名称。
# 应用场景
- 热点数据
查询频繁的表、字典表等。 - 复杂查询
耗时的计算、重复的查询数据等。