Spring Boot 默认缓存

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.mzph.cn/news/226205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Balking(犹豫)设计模式

多个线程监控某个共享变量&#xff0c;A线程监控到共享变量发生变化后即将触发某个动作&#xff0c;但此时发现有另外一个线程B已经针对该变量的变化开始了行动&#xff0c;因此A便放弃了准备开始的工作&#xff0c;我们把这样的线程交互称为Balking&#xff08;犹豫&#xff0…

小红书商品详情API:电商助力

一、引言 随着互联网的普及和电商行业的快速发展&#xff0c;消费者对于商品信息的获取方式也在不断变化。小红书作为一款以内容分享为主的社交电商平台&#xff0c;吸引了大量用户。为了满足用户对商品信息的快速获取需求&#xff0c;小红书提供了商品详情API接口。本文将探讨…

Stream流中anyMatch和allMatch和noneMatch的区别

1.anyMatch 两个集合的交集 Testpublic void a17() {List<User> list new ArrayList<>();list.add(new User("张三", 12, "南京"));list.add(new User("李四", 13, "北京"));list.add(new User("王五", 14, …

python调用属性一样调用方法property

1 python调用属性一样调用方法property python通过property达到像调用属性一样来调用方法。 存在两种方式&#xff1a; &#xff08;1&#xff09; 类属性&#xff1a;在类中定义值为property对象的类属性。 &#xff08;2&#xff09; 装饰器&#xff1a;在方法上应用装饰…

Web测试、APP测试常用技巧(错过你一定会后悔)

1. web元素定位七种方式 优先使用的6种 find_element_by_id (返回一个元素)find_element(s)_by_class_name (根据类名获取元素列表)find_element(s)_by_name (根据标签的name属性值返回包含标签对象元素的列表)find_element(s)_by_link_text (根据连接文本获取元素列表)find_…

linux环境安装可操作图库语言Gremlin的图框架HugeGraph

原创/朱季谦 若你还没接触过图数据库&#xff0c;可能看到这个概念时&#xff0c;会比较蒙蔽。 图是什么&#xff1f;图数据库又是什么&#xff1f; 首先&#xff0c;在数据结构中&#xff0c;图是一种由顶点&#xff08;vertex&#xff09;集合及顶点间关系集合组成的一种非…

常见数据结构

数据结构概述 数据结构是计算机底层存储、组织数据的方式&#xff0c;是指数据相互之间是以什么方式排列在一起的。 通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。 栈 栈数据结构的执行特点&#xff1a;后进先出&#xff0c;先进后出。 栈模型…

探索灵活性与可维护性的利器:策略(Strategy)模式详解

目录 ​编辑 1. 策略模式概述&#xff1a; 2. 主要角色&#xff1a; 3. 实例场景&#xff1a; 4. 具体实现步骤&#xff1a; 步骤一&#xff1a;定义策略接口 5. 使用策略模式的客户端代码&#xff1a; 总结&#xff1a; 我的其他博客 1. 策略模式概述&#xff1a; 策…

python【matplotlib】鼠标拖动滚动缩放坐标范围和拖动图例共存

背景 根据前面的博文&#xff1a; python【matplotlib】画图鼠标缩放拖动动态改变坐标轴范围 和Python【Matplotlib】图例可拖动改变位置 两个博文&#xff0c;博主考虑了一下&#xff0c;如何将两者的功能结合起来&#xff0c;让二者共存。 只需根据Python【Matplotlib】鼠标…

域名、DNS 和 IP是什么?网站搭建的必备知识,一文搞定

在正式进行WordPress站点搭建前&#xff0c;有一些最基础的知识是必备的&#xff0c;这篇文章会详细介绍给大家。 一、域名、DNS和IP的关系 域名、DNS和IP是互联网上的三个重要的概念&#xff0c;它们之间有着密切的联系&#xff0c;也影响着我们访问网站的方式和效果。接下来…

JNA实现JAVA调用C/C++动态库

1.JNA JNA全称Java Native Access&#xff0c;是一个建立在经典的JNI技术之上的Java开源框架&#xff08;https://github.com/twall/jna&#xff09;。JNA提供一组Java工具类用于在运行期动态访问系统本地库&#xff08;native library&#xff1a;如Window的dll&#xff09;而…

5.1 C++11强类型枚举

一、C枚举的缺陷 1.类型冲突 枚举值和类型都是全局可见的&#xff0c; 与正常C的namespace、类等都是格格不入的&#xff0c;并且还容易导致冲突。 enum Type { General, Light, Medium, Heavy }; enum Category { General, Pistol, MachineGun, Cannon }; 如果在相同作用域…

【CSS】用 CSS 写一个渐变色边框的输入框

Using_CSS_gradients MDN 多渐变色输入框&#xff0c;群友问了下&#xff0c;就试着写了下&#xff0c;看了看 css 渐变色 MDN 文档&#xff0c;其实很简单&#xff0c;代码记录下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta ch…

uniapp实现检查版本检测,更新

1.首先需要获取当前app的版本 const systemInfo uni.getSystemInfoSync();// 应用程序版本号// #ifdef APPme.version systemInfo.appWgtVersion;// #endif// #ifdef H5me.version systemInfo.appVersion;// #endif2.在获取到服务器保存的app版本 3.点击按钮验证版本号 //…

JS的箭头函数this:

箭头函数不会创建自己的this&#xff0c;它只会从自己的作用域链的上一层沿用this。 具体看实例&#xff1a; //以前&#xff1a;谁调用的这个函数 this就指向谁// console.log(this);//window// function fn(){// console.log(this);//window 因为这个函数也是window调用…

lwIP 细节之五:accept 回调函数是何时调用的

使用 lwIP 协议栈进行 TCP 裸机编程&#xff0c;其本质就是编写协议栈指定的各种回调函数。将你的应用逻辑封装成函数&#xff0c;注册到协议栈&#xff0c;在适当的时候&#xff0c;由协议栈自动调用&#xff0c;所以称为回调。 注&#xff1a;除非特别说明&#xff0c;以下内…

k8s-deployment initcontainers提前监测svc可用

背景&#xff1a;项目deploy需要依赖svc启动&#xff0c;但是k8s启动deploy是无序的&#xff0c;就需要人为控制 Init Container 应用场景 讲解了 Init Container 的使用&#xff0c;接下来介绍 Init Container 有哪些应用场景。 在很多的应用场景中&#xff0c;应用在启动之…

车载以太网-DoIP

文章目录 车载以太网DoIP协议(Diagnostics over Internet Protocol)DoIP协议的报文格式DoIP报文类型DoIP协议的完整流程车载以太网DoIP协议(Diagnostics over Internet Protocol) 车载以太网DoIP协议(Diagnostics over Internet Protocol)是一种用于车辆诊断的网络协议,…

Python中类与对象

一、前言 面向对象是一种设计哲学和方法论。它并非必需&#xff0c;不使用面向对象也可以编程。但有了面向对象&#xff0c;可以把程序组织得更有条理&#xff0c;让设计过程更加愉悦和轻松。面向对象&#xff1a;再解决问题的时候关注的是解决问题所需要的对象。 Python是一种…

2024GoCN线下活动全面启动,赠送深圳MeetUp门票

2024年GoCN社区将全面启动一系列令人期待的线下活动---不仅将在北京、上海、深圳、武汉、成都、杭州、广州、西安等地举办 meetup&#xff0c;还将在北京和上海举办 GopherChina 大会。 2024议题征集通道已开启&#xff0c;欢迎各位有实战经验、独特观点的Gopher前来分享~ 2024…