本文最后更新于46 天前,其中的信息可能已经过时,如有错误请发送邮件到1169063119@qq.com
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache提供一层抽象,底层可以切换不同地缓存实现,例如:
- EHCache
- Caffeine
- Redis
常用注解:
@EnableCaching | 开启缓存注解功能,通常加载启动类上 |
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值发那个在缓存中 |
@CachePut | 将方法的返回值放在缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
Spring Cache 让你能够:
以最小的侵入性为方法添加缓存行为:通过在方法上添加简单的注解(如 @Cacheable
, @CachePut
, @CacheEvict
),即可实现方法结果的缓存、更新缓存或清除缓存。
屏蔽底层缓存实现的差异:无论你底层使用的是 Redis、Memcached、Ehcache、Caffeine、ConcurrentMap 还是其他兼容 Spring Cache API 的缓存,你的业务代码(调用缓存的方法)基本保持不变。你只需要配置好对应的缓存管理器 (CacheManager
) 即可。
减少样板代码:你不需要手动编写大量的 if (cache.get(key) != null) { return cache.get(key); } else { ... }
这样的重复性代码。Spring Cache 在背后通过 AOP (面向切面编程) 自动帮你处理这些逻辑。
配置Spring Cache
@Configuration
@EnableCaching
public class CacheConfig {
// 使用 Caffeine
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("products", "users");
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES)); // 设置过期时间
return cacheManager;
}
// 或者使用 Redis (需要 spring-boot-starter-data-redis)
// @Bean
// public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
// return RedisCacheManager.create(connectionFactory);
// }
}
Spring Cache的主要优势
- 简化开发:通过声明式注解,极大地简化了缓存逻辑的集成,减少了重复的样板代码。
- 抽象解耦:业务代码与具体的缓存技术实现解耦。更换缓存提供者通常只需要修改
CacheManager
的配置。 - 一致性:提供了一套统一的缓存操作 API。
- 灵活性:支持 SpEL 表达式定义缓存 key 和条件,功能强大。
注意
- 缓存一致性:缓存数据与底层数据源(如数据库)可能存在不一致。需要根据业务场景设计合理的缓存策略(过期时间、
@CacheEvict
的触发点)或考虑使用事务性缓存。 - 缓存穿透/击穿/雪崩:Spring Cache 提供的是抽象,这些缓存常见问题需要开发者结合具体缓存提供者的特性和配置来处理(例如在 Redis 中使用布隆过滤器防穿透、设置随机过期时间防雪崩)。
- 序列化:当使用分布式缓存(如 Redis)时,需要确保被缓存的对象是可序列化的。
- 内部方法调用:基于 AOP 的缓存注解在同一个类内部方法调用时可能失效(因为代理对象的问题),通常需要将缓存方法抽取到另一个 Bean 中或使用其他方式(如 AspectJ)解决。