1. 为什么我们需要Spring Boot缓存
在Web应用开发中,性能优化是个永恒的话题。我经历过一个电商项目,商品详情页的QPS在促销期间能达到5000+,每次请求都要查询数据库获取商品信息、库存数据、用户评价等,数据库很快成为瓶颈。这就是典型的缓存适用场景 - 高频读取但数据变更不频繁。
Spring Cache抽象层提供了一种声明式的缓存解决方案,而@Cacheable就是其中最核心的注解。它通过AOP在方法执行前后自动处理缓存逻辑,开发者只需关注业务代码。这种设计完美体现了Spring"约定优于配置"的理念。
注意:缓存虽好但不能滥用。适合缓存的典型特征包括:计算成本高、数据实时性要求不高、访问频率高。像订单支付状态这种强实时数据就不适合缓存。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. @Cacheable注解深度解析
2.1 基础使用姿势
最简单的使用方式就是在方法上添加注解:
java复制@Cacheable("products")
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
这段代码实现了:
- 方法首次调用时正常执行方法体
- 将返回值以id为键存入名为"products"的缓存
- 后续相同id请求直接返回缓存值
缓存名称("products")对应配置中的缓存管理器(CacheManager)。Spring支持多种缓存实现,默认使用ConcurrentMapCacheManager。
2.2 核心参数详解
@Cacheable提供了丰富的配置参数:
| 参数名 | 作用 | 示例 |
|---|---|---|
| value/cacheNames | 指定缓存名称 | @Cacheable("products") |
| key | 自定义缓存键 | @Cacheable(key = "#id") |
| condition | 执行条件 | @Cacheable(condition="#id>10") |
| unless | 否决缓存 | @Cacheable(unless="#result==null") |
| keyGenerator | 键生成器 | 实现KeyGenerator接口 |
| cacheManager | 指定缓存管理器 | 配合@Bean使用 |
| cacheResolver | 缓存解析器 | 高级定制场景 |
2.3 键生成策略
缓存键的生成直接影响缓存命中率。默认规则是:
- 如果没有参数,使用SimpleKey.EMPTY
- 如果只有一个参数,直接使用该参数
- 多个参数则使用包含所有参数的SimpleKey
自定义键的几种方式:
java复制// SpEL表达式
@Cacheable(key = "#user.id + ':' + #product.id")
// 调用方法
@Cacheable(key = "T(java.util.UUID).randomUUID().toString()")
// 实现KeyGenerator
public class CustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object
