Spring Cache 入门教程:用注解轻松实现缓存(Redis为例子)
在日常开发中,我们经常会遇到“重复查询数据库”的情况,比如查询用户信息、商品信息、文章列表等。
如果访问量大,这些操作会给数据库带来压力。
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要加个注解就能实现缓存功能
Spring Cache 的使用也非常简单,只需要导入不同的依赖底层就能切换不同的缓存实现,如Redis,EHcache
下面我们通过几个简单的例子来入门 Spring Cache。
一.开启 Spring Cache
1.导入Spring Cache的依赖

2.在Spring boot 的启动类上加这个注解@EnableCaching ,这样就开启了缓存功能。

二.常用注解(掌握这三个就够了)
| 注解 | 作用 |
|---|---|
@Cacheable | 用于方法查询。当传入的 key 在缓存中已有数据时,直接返回缓存结果,不执行方法体;若缓存不存在,则执行方法、获取结果并写入缓存,适用于“查多改少”的接口。 |
@CachePut | 无论缓存中是否存在都会执行方法体,将方法返回值放入缓存中并覆盖旧值。常用于更新、修改、保存数据时,确保数据库与缓存一致,不会跳过方法。 |
@CacheEvict | 用于移除缓存中的数据,可删除指定 key,也可通allEntries=true 清空整个缓存区域。适用于删除数据、更新列表数据后手动清理缓存等场景,保证缓存与数据库同步。 |
三个注解的参数写法总结(最常用)
| 注解 | 必需参数 | 常用参数 | 示例 |
|---|---|---|---|
| @Cacheable | value | key, unless, condition | @Cacheable(value = "user", key = "#id", unless = "#result == null") 如果返回结果 #result == null,就不写入缓存。 |
| @CachePut | value | key, unless, condition | @Cacheable(value = “user”, key = “#id”, condition = “#id > 1000”) 只有当 id > 1000 时,Spring 才会去查缓存 / 写缓存。 否则直接执行方法,不用缓存。 |
| @CacheEvict | value | key, allEntries, beforeInvocation | @CacheEvict(value = "user", key = "#id", beforeInvocation = true) 方法执行前立刻删除缓存,不管后面方法是否抛异常。 |
| 注解参数 | 用于哪个注解 | 作用 |
|---|---|---|
condition | @Cacheable @CachePut @CacheEvict | 满足条件才执行缓存逻辑(执行前判断) |
unless | @Cacheable @CachePut | 方法执行后,如果条件为 true,则不缓存结果 |
allEntries | @CacheEvict | 是否清空整个缓存空间 |
beforeInvocation | @CacheEvict | 是否在方法调用前就清除缓存(默认是方法调用后) |
1.@Cacheable —— 查询时使用
注:是Springframework的这个

使用方法:

说明:程序执行到@Cacheable处会先去查询你的redis有无数据,如果无就执行getById这个方法并将数据存储到redis里面,如果有就直接从redis拿出数据,不执行方法。
2.@CachePut —— 修改时更新缓存

也能这样写@CachePut(value = “user”, key = “#result.id”),区别就是一个是从方法参数取 id,一个是从返回对象取id,但要注意
使用 #result 必须保证方法返回的对象不是 null并且返回值里要包含 id
key的写法很多,这两种写法最常用。
说明:程序执行到 @CachePut 注解时,无论 redis 中是否已有缓存,都会先执行方法本身,执行完成后再把方法的返回结果更新到 redis 的指定 key 中。即:方法必定执行,并覆盖(或写入)缓存。
3.@CacheEvict —— 删除缓存
基本用法:删除一个 key:

清空整个缓存区域:

说明:程序执行到 @CacheEvict 注解时,会根据配置的 key 从 redis 中删除对应的缓存数据。如果设置了 allEntries = true,则会清空当前缓存空间下的所有数据。默认在方法执行完成后删除缓存,也可以通过 beforeInvocation = true 实现在方法执行前删除。
三.对比,不用 Spring Cache(手写缓存) vs 使用 Spring Cache
不用 Spring Cache(手写 Redis 逻辑)
@Servicepublic class UserService {
@Autowired private RedisTemplate<String, Object> redisTemplate;
@Autowired private UserMapper userMapper;
public User getUserById(Long id) { String key = "user:" + id;
// 1. 查询缓存 User user = (User) redisTemplate.opsForValue().get(key); if (user != null) { return user; // 2. 有缓存,直接返回 }
// 3. 无缓存,查数据库 user = userMapper.findById(id); if (user != null) { // 4. 写入缓存 redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS); }
return user; }}缺点:
每次都要写 key
要手动处理缓存过期时间
需要自己写“查 → 判断 → 回源 → 存”的模板逻辑
代码重复率高
容易漏写缓存逻辑导致不一致
使用 Spring Cache(自动处理缓存逻辑)
@Servicepublic class UserService {
@Autowired private UserMapper userMapper;
@Cacheable(value = "user", key = "#id") public User getUserById(Long id) { return userMapper.findById(id); }}说明(自动完成刚才手写的逻辑):
先查缓存 user::id
如果有 → 直接返回,不执行方法
如果没有 → 执行方法查数据库
方法返回值自动写入 redis
优点:
一行注解自动实现读缓存
不需要自己写 redisTemplate
不需要写逻辑判断缓存是否存在
不需要自己写 key 拼接
不需要自己设置缓存过期时间(可全局配置)
更简洁、可读性强、可维护性高。
部分信息可能已经过时









