缓存注解详解
2026/1/15大约 3 分钟SpringSpring CacheJava缓存后端
缓存注解详解
@Cacheable
@Cacheable 是最常用的缓存注解,用于标记方法的返回值需要被缓存。
基本用法
@Cacheable("users")
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}核心属性
| 属性 | 说明 | 示例 |
|---|---|---|
| value/cacheNames | 缓存名称 | @Cacheable("users") |
| key | 缓存 Key | @Cacheable(key = "#id") |
| condition | 缓存条件 | @Cacheable(condition = "#id > 0") |
| unless | 排除条件 | @Cacheable(unless = "#result == null") |
| keyGenerator | Key 生成器 | @Cacheable(keyGenerator = "myKeyGen") |
| cacheManager | 缓存管理器 | @Cacheable(cacheManager = "redisCM") |
| sync | 同步模式 | @Cacheable(sync = true) |
完整示例
@Cacheable(
value = "users",
key = "#id",
condition = "#id > 0",
unless = "#result == null"
)
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}@CachePut
@CachePut 每次都会执行方法,并将结果更新到缓存。
// 更新用户后同步更新缓存
@CachePut(value = "users", key = "#user.id")
public User update(User user) {
return userRepository.save(user);
}
// 新增用户后加入缓存
@CachePut(value = "users", key = "#result.id")
public User create(User user) {
return userRepository.save(user);
}@Cacheable vs @CachePut
@CacheEvict
@CacheEvict 用于删除缓存。
基本用法
// 删除指定 Key 的缓存
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
// 清空整个缓存
@CacheEvict(value = "users", allEntries = true)
public void clearCache() {
// 清空 users 缓存
}
// 方法执行前删除缓存
@CacheEvict(value = "users", key = "#id", beforeInvocation = true)
public void deleteWithException(Long id) {
userRepository.deleteById(id);
// 即使抛异常,缓存也已删除
}核心属性
| 属性 | 说明 | 默认值 |
|---|---|---|
| allEntries | 是否清空所有缓存 | false |
| beforeInvocation | 是否在方法执行前删除 | false |
@Caching
@Caching 用于组合多个缓存操作。
@Caching(
cacheable = {
@Cacheable(value = "users", key = "#id")
},
put = {
@CachePut(value = "users", key = "#result.username")
},
evict = {
@CacheEvict(value = "userList", allEntries = true)
}
)
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}实际场景
// 更新用户时:更新多个缓存 Key,清空列表缓存
@Caching(
put = {
@CachePut(value = "users", key = "#user.id"),
@CachePut(value = "users", key = "#user.username")
},
evict = {
@CacheEvict(value = "userList", allEntries = true)
}
)
public User update(User user) {
return userRepository.save(user);
}@CacheConfig
@CacheConfig 用于类级别的缓存配置,避免重复配置。
@Service
@CacheConfig(cacheNames = "users", cacheManager = "caffeineCacheManager")
public class UserService {
// 继承类级别配置
@Cacheable(key = "#id")
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}
@CachePut(key = "#user.id")
public User update(User user) {
return userRepository.save(user);
}
@CacheEvict(key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
}SpEL 表达式
Spring Cache 支持使用 SpEL 表达式动态生成 Key 和条件。
内置变量
| 变量 | 说明 | 示例 |
|---|---|---|
#root.method | 当前方法 | #root.method.name |
#root.target | 目标对象 | #root.target.class |
#root.caches | 缓存集合 | #root.caches[0].name |
#root.args | 方法参数数组 | #root.args[0] |
#参数名 | 方法参数 | #id, #user |
#p0, #a0 | 第一个参数 | #p0, #a0 |
#result | 方法返回值 | #result.id |
Key 生成示例
// 使用参数名
@Cacheable(value = "users", key = "#id")
// 使用参数索引
@Cacheable(value = "users", key = "#p0")
// 组合多个参数
@Cacheable(value = "users", key = "#name + ':' + #age")
// 使用对象属性
@Cacheable(value = "users", key = "#user.id")
// 使用方法调用
@Cacheable(value = "users", key = "#user.getName().toUpperCase()")
// 使用条件表达式
@Cacheable(value = "users", key = "#id != null ? #id : 'default'")条件表达式示例
// condition:满足条件才缓存
@Cacheable(value = "users", key = "#id", condition = "#id > 0")
// unless:满足条件不缓存(在方法执行后判断)
@Cacheable(value = "users", key = "#id", unless = "#result == null")
// 组合使用
@Cacheable(
value = "users",
key = "#id",
condition = "#id > 0",
unless = "#result?.status == 'DELETED'"
)
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}自定义 KeyGenerator
@Configuration
public class CacheConfig {
@Bean
public KeyGenerator customKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append(":");
sb.append(method.getName());
sb.append(":");
for (Object param : params) {
sb.append(param.toString());
sb.append("_");
}
return sb.toString();
};
}
}
// 使用自定义 KeyGenerator
@Cacheable(value = "users", keyGenerator = "customKeyGenerator")
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}小结
Spring Cache 提供了丰富的注解来满足各种缓存场景:@Cacheable 用于查询缓存,@CachePut 用于更新缓存,@CacheEvict 用于删除缓存,@Caching 用于组合操作,@CacheConfig 用于类级别配置。结合 SpEL 表达式,可以实现灵活的缓存策略。
面试题预览
常见面试题
- @Cacheable 和 @CachePut 的区别是什么?
- condition 和 unless 有什么区别?
- 如何自定义缓存 Key 的生成策略?
