引言
在现代应用程序中,缓存是提高性能和响应速度的重要手段。Spring框架提供了一组强大的缓存注解,其中包括 @Cacheable、@CacheEvict 和 @CachePut。让我们深入了解这些注解的用途和适用场景。
Spring缓存的发展
Spring 3.x
- 基础支持: 在 Spring 3.x 版本中,引入了 org.springframework.cache.CacheManager
接口来实现缓存管理。它提供了基本的缓存操作接口,如 get()、put() 和 evict()。
XML配置: 通过 XML配置文件声明缓存管理器和缓存策略。
Spring 4.x
- 注解支持: 引入了注解支持,包括 @Cacheable、@CacheEvict 和 @CachePut 等。这些注解提供了更便捷的方式来管理缓存,减少了冗余的代码。
- Caching注解: @Caching注解的引入,允许在一个方法上同时应用多个缓存注解,提供更灵活的缓存配置。
Spring 5.x
- 注解进一步优化: 对缓存注解进行了进一步的优化和增强,使其更加灵活和功能更加强大。
- 更多缓存支持: 对多种缓存系统提供更丰富的支持,如Redis、Ehcache、Caffeine 等。引入了更多针对这些缓存系统的配置和优化选项。
Spring缓存注解概述
这些注解允许对方法的返回值进行缓存、清除缓存或者强制更新缓存。让我们逐个来看。
如何使用Spring Cache
启用缓存支持: 在 Spring 配置中启用缓存支持,可通过在配置类上添加 @EnableCaching 注解来完成。 标记缓存注解:
@EnableCaching
@Configuration
public class AppConfig {
// ...
}
在需要缓存的方法上标记对应的缓存注解,比如 @Cacheable、@CacheEvict 或 @CachePut。
@Cacheable注解
@Cacheable 允许将方法的返回值缓存起来,以便在后续相同参数调用时直接返回缓存值,无需重新执行方法体。
@Cacheable(value = "books", key = "#isbn")
public Book findBookByIsbn(String isbn) {
// 查询数据库获取书籍信息
}
@CachePut注解
@CachePut 可以确保方法被调用,并将其返回值放入缓存中,通常用于更新缓存而不是直接查询。
@CachePut(value = "books", key = "#book.isbn")
public Book updateBook(Book book) {
// 更新数据库中的书籍信息并返回
return book;
}
@CacheEvict注解
CacheEvict 可以清除特定缓存中的某些项
@CacheEvict(value = "books", key = "#isbn")
public void deleteBook(String isbn) {
// 从数据库中删除书籍信息
}
@Caching注解
@Caching 允许同时应用多个缓存注解,提供更灵活的缓存策略,可在一个方法上配置多个缓存操作。
@Caching(
cacheable = {
@Cacheable(value = "books", key = "#isbn")
},
evict = {
@CacheEvict(value = "books", key = "#isbn", beforeInvocation = true)
}
)
public void deleteBook(String isbn) {
// 从数据库中删除书籍信息
}
使用Redis管理缓存
配置Redis缓存管理器:
Spring提供了RedisCacheManager用于管理Redis缓存。
@Bean
public RedisConnectionFactory redisConnectionFactory() {
// 配置Redis连接工厂
}
@Bean
public RedisCacheManager cacheManager() {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60)) // 设置缓存失效时间
.disableCachingNullValues();
return RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(cacheConfig)
.build();
}
失效的场景和注意事项
场景:
- 在同一个类中调用另一个未被代理对象包装的方法。
- 事务内部方法调用。
- 异步方法调用。
- 使用同一个类中的对象调用方法。
这些情况会导致缓存失效,因为Spring的缓存是基于代理对象实现的,无法拦截到以上场景的调用,因此无法正确应用缓存。
结语
通过了解 Spring 缓存注解的功能和不同使用场景,我们可以更好地设计和管理缓存策略,以提高应用程序的性能和响应速度。