Spring Boot 默认缓存

news/2024/11/7 18:00:54/

Spring 提供了三个常用的注解:@Cacheable、@CachePut 和 @CacheEvict

一、@Cacheable,@CachePut,@CacheEvict区别
当使用缓存时,Spring 提供了三个常用的注解:@Cacheable、@CachePut 和 @CacheEvict,它们的区别如下:

@Cacheable 注解:

作用:将方法的返回值缓存起来,以便下次相同的方法调用时可以直接从缓存中获取结果。

使用场景:适用于读取操作频繁,但数据很少改变的场景。

示例代码:

@Cacheable(value = "products", key = "#productId") 
public Product getProductById(Long productId) { 
// 从数据库中获取产品信息 
}

在上述示例中,使用 @Cacheable 注解将 getProductById 方法的返回值缓存起来,缓存的名称为 “products”。每次调用该方法时,如果缓存中存在对应的结果,就直接返回缓存值;否则执行方法逻辑,并将结果放入缓存中。

@CachePut 注解:

作用:将方法的返回值更新到缓存中。

使用场景:适用于写入或更新操作,需要将结果放入缓存并确保缓存的数据是最新的。

示例代码:

@CachePut(value = "products", key = "#product.id") 
public Product saveProduct(Product product) { 
// 保存产品信息到数据库 return product; 
}

在上述示例中,使用 @CachePut 注解将 saveProduct 方法的返回值放入缓存中,缓存的名称为 “products”。每次调用该方法时,无论缓存中是否存在对应的值,都会执行方法逻辑,并将结果更新到缓存中。

@CacheEvict 注解:

作用:从缓存中移除一个或多个缓存项。

使用场景:适用于删除操作或数据更新后的缓存清理。

示例代码:

@CacheEvict(value = "products", key = "#productId") 
public void deleteProduct(Long productId) { 
// 从数据库中删除产品信息}

在上述示例中,使用 @CacheEvict 注解将 deleteProduct 方法执行后,将缓存中指定 productId 的缓存项移除,缓存的名称为 “products”。

二、进阶使用
进阶使用 @Cacheable、@CachePut 和 @CacheEvict 注解的一些注意事项和高级用法包括:

多缓存管理器支持:如果应用程序中使用了多个缓存管理器,可以使用 cacheManager 属性指定具体的缓存管理器。

@Cacheable(value = "products", key = "#productId", cacheManager = "cacheManager1") 
public Product getProductById(Long productId) { // ... }

条件缓存:可以使用 SpEL 表达式在注解中定义条件,只有满足条件时才进行缓存操作。

@Cacheable(value = "products", key = "#productId", condition = "#productId > 0") 
public Product getProductById(Long productId) { // ... }

自定义缓存策略:通过实现 CacheResolver 接口或者使用 cacheResolver 属性,可以自定义缓存的解析和管理逻辑。

@Cacheable(value = "products", key = "#productId", cacheResolver = "customCacheResolver") 
public Product getProductById(Long productId) { // ... }

缓存更新时机:可以使用 @CachePut 注解在方法执行后手动触发缓存更新,而不是每次方法调用都更新缓存。

@CachePut(value = "products", key = "#product.id") 
public Product updateProduct(Product product) { // ... return product; }

缓存清除策略:使用 @CacheEvict 注解时,可以通过 beforeInvocation 属性来控制清除缓存的时机,默认是在方法执行后清除缓存。

@CacheEvict(value = "products", key = "#productId", beforeInvocation = true) 
public void deleteProduct(Long productId) { // ... }

缓存注解继承:可以使用注解继承方式,简化对多个方法应用相同缓存注解的操作。

@Inherited @Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
@Cacheable(value = "products", key = "#productId") 
public @interface CachedProduct {// ...}@CachedProduct 
public Product getProductById(Long productId) { // ...} 
@CachedProduct 
public List<Product> getAllProducts() {// ...}

自定义缓存键生成策略:可以使用 keyGenerator 属性指定自定义的缓存键生成器。

@Cacheable(value = "products",keyGenerator = "customKeyGenerator") public Product getProductById(Long productId) {// ... }

SpEL 表达式使用:在注解的属性值中可以使用 SpEL 表达式,动态计算缓存键、条件等。

@Cacheable(value = "products", key = "'product:' + #productId") 
public Product getProductById(Long productId) { 
// ...}

缓存注解的优先级:在方法上同时使用多个缓存注解时,它们的执行顺序和优先级可以通过 @Order 注解进行控制。

@Cacheable(value = "products", key = "#productId") 
@CachePut(value = "products", key = "#productId") 
@Order(1) 
public Product getProductById(Long productId) { // ... }

配置缓存过期时间:可以使用缓存管理器的配置来设置缓存的过期时间,或者在注解中通过 expiration 属性指定缓存的过期时间。

@Configuration 
@EnableCaching 
public class CacheConfig extends CachingConfigurerSupport { 
// ... 
@Override public CacheManager cacheManager() 
{ 
SimpleCacheManager cacheManager = new SimpleCacheManager(); 
// 设置缓存过期时间cacheManager.setCaches(Arrays.asList( new ConcurrentMapCache("products", getExpirationDuration(30)), // ...)); return cacheManager; } private Duration getExpirationDuration(int minutes) {return Duration.ofMinutes(minutes);} } @Cacheable(value = "products", key = "#productId", expiration = 10) public Product getProductById(Long productId) {// ... }

缓存条件判断:可以使用 condition 属性在注解中指定一个 SpEL 表达式,根据条件判断是否执行缓存操作。

@Cacheable(value = "products",key = "#productId", condition = "#productId > 0")public Product getProductById(Long productId) { // ... }

同步缓存操作:使用 @CachePut 注解可以实现同步缓存操作,即先执行方法,然后更新缓存。

@CachePut(value = "products", key = "#product.id") 
public Product updateProduct(Product product) { 
// ... return product; }

缓存清除策略:@CacheEvict 注解可以用于清除缓存中的数据,可以通过 key 属性指定要清除的缓存项。

@CacheEvict(value = "products", key = "#productId") 
public void deleteProduct(Long productId) {// ... }

缓存注解顺序:当一个方法上同时存在多个缓存注解时,可以使用 @CacheConfig 注解或 @Order 注解来控制注解的执行顺序。

@CacheConfig(cacheNames = "products") 
public class ProductRepository { 
@Cacheable(key = "#id") 
@CachePut(key = "#result.id") 
public Product getProductById(Long id) { 
// ... 
} }

使用 SpEL 表达式:可以在注解中使用 SpEL 表达式动态地生成缓存键。

@Cacheable(value = "products", key = "'product:' + #productId") 
public Product getProductById(Long productId) {// ... }

缓存与事务管理:在使用缓存注解时,需要注意与事务管理的交互。默认情况下,Spring 的事务管理会在方法执行前将缓存清空,以保证数据的一致性。如果希望在事务提交后再执行缓存操作,可以使用 @CachePut 注解并将方法放在一个新的事务中。

@Transactional public void updateProduct(Product product) {// 更新数据库中的数据 // ... // 手动执行缓存操作updateProductCache(product); } @CachePut(value = "products", key = "#product.id") @Transactional(propagation = Propagation.REQUIRES_NEW) public Product updateProductCache(Product product) { // 更新缓存中的数据 // ... return product;}

多级缓存配置:可以配置多个级别的缓存,例如使用一级缓存作为本地缓存,二级缓存作为分布式缓存。可以通过 @CacheConfig 注解和 CacheManager 进行配置。

@CacheConfig(cacheNames = "products") 
public class ProductRepository { 
@Autowired private CacheManager cacheManager; 
@Cacheable(key = "#id", cacheManager = "localCacheManager") 
public Product getProductById(Long id) {// ... } @Cacheable(key = "#id", cacheManager = "distributedCacheManager") public Product getProductByIdFromDistributedCache(Long id) { // ...} }

缓存预热:可以在应用启动时,通过调用特定的方法来预先加载缓存数据,以提高系统的性能和响应速度。

@Component public class CachePreloader 
{ 
@Autowired private ProductRepository productRepository; 
@PostConstruct public void preloadCache() {List<Product> products = productRepository.getAllProducts(); for (Product product : products) { productRepository.getProductById(product.getId()); } } }

异步缓存操作:使用异步方式执行缓存操作,以减少对主线程的影响,提高系统的并发性能。

@CachePut(value = "products", key = "#product.id") 
@Async 
public CompletableFuture<Product> updateProductAsync(Product product) { // ... 
return CompletableFuture.completedFuture(product);}

以上是一些进阶用法和注意事项,它们可以帮助你更好地使用 @Cacheable、@CachePut 和 @CacheEvict 注解来管理缓存,并根据具体的业务需求和场景进行优化和配置。请根据实际情况选择合适的用法,并结合缓存框架和缓存管理器的文档进行深入研究和调整。

三、总结
@Cacheable 注解用于指示方法的结果应该被缓存,以提高后续对相同输入参数调用的性能。它会首先检查缓存中是否存在结果,如果存在,则直接返回缓存中的值;如果不存在,则执行方法并将结果存入缓存。可以通过设置缓存的键(key)来区分不同的缓存项。

@CachePut 注解用于指示方法的结果应该被缓存,但它每次都会执行方法并将结果存入缓存,不会像 @Cacheable 那样检查缓存中是否已存在结果。它常用于更新缓存中的数据,确保缓存的数据与数据库或其他数据源保持同步。

@CacheEvict 注解用于指示方法执行后应清除缓存中的某些项。可以通过设置缓存的键(key)来指定要清除的特定缓存项。它还提供了一些属性,如 allEntries 和 beforeInvocation,用于清除所有缓存项或在方法执行前清除缓存。

这些注解可以与不同的缓存提供程序集成,如 Spring Boot 默认的缓存提供程序 Caffeine、Ehcache、Redis 等。通过合理地使用这些注解,可以显著提高应用程序的性能和响应速度。


http://www.ppmy.cn/news/1272263.html

相关文章

k8syaml提供的几个有意思的功能,Kubernetes在线工具网站

k8syaml.cn 提供的几个有意思的功能。 一、yaml资源快速生成 之前编写operator的helm的时候就需要自己写deployment、service、configmap这些资源&#xff0c;那么多字段也记不清&#xff0c;都是先找个模版&#xff0c;然后copy改改&#xff0c;再看官方文档&#xff0c;添加…

07-抽象工厂

意图 提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 适用性 在以下的情况可以选择使用抽象工厂模式&#xff1a; 一个系统要独立于它的产品的创建、组合和表示。一个系统要由多个产品系列中的一个来配置。要强调一系列相关的产品对象的…

开机0xc000000e修复方式,电脑出现错误代码0xc000000e

0xc000000e是Windows操作系统中的一个常见错误代码。错误代码0xc000000e表示操作系统无法找到正确的启动设备或引导记录损坏&#xff0c;导致电脑无法正常启动。今天的这篇文章将和大家分享一些关于开机0xc000000e修复的方法。 一.电脑出现开机0xc000000e的原因 开机出现0xc00…

详细了解stm32---按键

提示&#xff1a;永远支持知识文档免费开源&#xff0c;喜欢的朋友们&#xff0c;点个关注吧&#xff01;蟹蟹&#xff01; 目录 一、了解按键 二、stm32f103按键分析 三、按键应用 一、了解按键 同学们&#xff0c;又见面了o(*&#xffe3;▽&#xffe3;*)ブ&#xff0c;最…

阿里云对象存储OSS外网流出流量异常增多导致费用上升的解决方法

本文介绍在使用阿里云的对象存储 OSS服务过程中&#xff0c;外网流量消耗异常增多并导致异常的费用支出这一情况的问题发现、问题定位与几种不同的问题解决方法。 细细数来&#xff0c;写博客已经有近3的历史了&#xff0c;这成为了一项已经陪伴我大半人生的工作&#xff1b;也…

uniapp常用api讲解

Uniapp是一个基于Vue.js的跨平台开发框架&#xff0c;可以同时开发微信小程序、H5、App等多个平台的应用。下面是Uniapp常用的API讲解&#xff1a; Vue.js的API Uniapp采用了Vue.js框架&#xff0c;因此可以直接使用Vue.js的API。例如&#xff1a;v-show、v-if、v-for、compu…

贝蒂详解<string.h>哦~(用法与实现)

目录 引言&#xff1a; &#xff08;一&#xff09;字符函数和字符串函数 1.简介 2.strlen()函数 2.1用法 2.2实例 2.3 实现strlen() &#xff08;1&#xff09;计数法 &#xff08;2&#xff09;递归法 &#xff08;3&#xff09; 指针-指针 2.4sizeof和strlen()的区别 3.s…

CentOS新系统工具安装

时区设置 ## 查看当前时区 timedatectl | grep "Time zone" ## 查看时区列表 thiimedatectl list-timezones ## 设置时区 sudo timedatectl set-timezone Asia/ShanghaiCentOS7桌面怎么校准时间&#xff1f;&#xff08;设置时区&#xff09; 安装Docker 环境 # …