Spring 框架——@Retryable 注解与 @Recover 注解

目录
  • 1.@Retryable 注解介绍
  • 2.示例:如何使用 @Retryable 注解
    • 2.1.添加依赖
    • 2.2.启用重试功能
    • 2.3.使用 @Retryable 注解
    • 2.4.解释
  • 3.@Recover 注解介绍
  • 4.示例:@Recover 注解与 @Retryable 注解配合使用
    • 4.1.两者配合使用
    • 4.2.两者对应关系
  • 5.其他注意事项

1.@Retryable 注解介绍

(1)@Retryable注解用于实现方法的重试机制,通常用于处理暂时性的失败,确保在特定条件下自动重试方法调用。它常用于微服务和分布式系统中,特别是在处理网络请求或外部服务时。@Retryable注解的代码如下所示:

package org.springframework.retry.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Retryable { String recover() default ""; String interceptor() default ""; /** @deprecated */ @Deprecated Class<? extends Throwable>[] value() default {}; /** @deprecated */ @AliasFor("retryFor") @Deprecated Class<? extends Throwable>[] include() default {}; @AliasFor("include") Class<? extends Throwable>[] retryFor() default {}; /** @deprecated */ @Deprecated @AliasFor("noRetryFor") Class<? extends Throwable>[] exclude() default {}; @AliasFor("exclude") Class<? extends Throwable>[] noRetryFor() default {}; Class<? extends Throwable>[] notRecoverable() default {}; String label() default ""; boolean stateful() default false; int maxAttempts() default 3; String maxAttemptsExpression() default ""; Backoff backoff() default @Backoff; String exceptionExpression() default ""; String[] listeners() default {}; }

(2)@Retryable注解的常用属性如下:

  • value:指定要重试的异常类型。可以是多个异常类型,例如@Retryable(value = {IOException.class, TimeoutException.class})
  • retryFor:另一个方式指定需要重试的异常类型。用法与 value 类似。
  • include:指定哪些异常类型应该被包含在重试范围内。与 value 类似,但用于更精确的控制重试条件。
  • exclude:指定不需要重试的异常类型。例如,@Retryable(exclude = {NullPointerException.class})表示遇到 NullPointerException 时不进行重试。
  • maxAttempts:设置最大重试次数。例如,@Retryable(maxAttempts = 5)表示最多重试 5 次。
  • backoff:配置重试间隔和增量。可以使用 Backoff 类中的属性来设定,例如@Retryable(backoff = @Backoff(delay = 2000, multiplier = 2))表示重试延迟初始为 2000 毫秒,每次重试间隔都会是上一次的两倍。
  • recover:用于指定在所有重试尝试失败后,调用的恢复方法。这个方法通常用于处理最终失败后的逻辑,例如清理资源或记录错误。具体用法见后续的@Recover注解与@Retryable注解配合使用。

2.示例:如何使用 @Retryable 注解

假设你有一个服务类PaymentService,其方法processPayment可能会因临时网络问题而失败。你希望在遇到网络异常时自动重试几次。

2.1.添加依赖

首先,确保你的 Spring 项目中包含了spring-retryspring-boot-starter-aop依赖。在pom.xml中添加如下内容:

<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>

2.2.启用重试功能

在你的 Spring Boot 应用程序中,使用@EnableRetry注解来启用重试功能:

import org.springframework.retry.annotation.EnableRetry; import org.springframework.stereotype.Service; @EnableRetry @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

2.3.使用 @Retryable 注解

在需要进行重试的方法上添加@Retryable注解。例如,假设processPayment方法需要重试:

import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; @Service public class PaymentService { @Retryable( value = {PaymentException.class}, // 需要重试的异常类型 maxAttempts = 5, //最大重试次数为 5 backoff = @Backoff(delay = 2000, multiplier = 2, maxDelay = 100000) //重试策略:重试延迟初始为 2000 毫秒,每次重试间隔都会是上一次的两倍,最大重试延迟为 100000 毫秒 ) public void processPayment() throws PaymentException { //模拟处理支付的逻辑,如果发生 PaymentException 则会进行重试 if (someConditionFails()) { throw new PaymentException("Payment processing failed."); } //处理支付成功 } private boolean someConditionFails() { //模拟条件失败 return true; } }

2.4.解释

(1)@Retryable注解的三个属性解释如下:

  • value: 指定需要重试的异常类型,这里是PaymentException。如果方法抛出这种异常,将会触发重试机制。
  • maxAttempts: 指定最大重试次数,这里设置为 5 次。
  • backoff: 配置重试的间隔和增量。这包括delay(首次重试的延迟时间),multiplier(每次重试时延迟时间的倍数增长),maxDelay(最大延迟时间)。

(2)在这个例子中,如果processPayment方法抛出PaymentException,系统将自动重试最多 5 次,每次重试之间的间隔将从 2 秒开始,并且每次重试时延迟时间会加倍,直到达到最大延迟时间。

3.@Recover 注解介绍

@Recover注解用于定义当所有重试尝试失败后要执行的恢复逻辑。它通常与@Retryable注解配合使用,它所标记的方法会在@Retryable注解的方法所有重试失败后被调用,处理最终的错误恢复,例如记录日志、通知用户或执行补救措施。其代码如下所示:

package org.springframework.retry.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Import({RetryConfiguration.class}) @Documented public @interface Recover { }

4.示例:@Recover 注解与 @Retryable 注解配合使用

4.1.两者配合使用

(1)添加依赖与启用重试功能(与 2.1 和 2.2 相同)。

(2)示例代码如下:

package com.example.myexample.service.impl; import com.example.myexample.service.AnnotationTestService; import lombok.extern.slf4j.Slf4j; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Recover; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; import java.io.IOException; @Slf4j @Service public class AnnotationTestServiceImpl implements AnnotationTestService { //定义一个需要重试的方法 @Override @Retryable( recover = "recover", value = IOException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000)) public void performOperation() throws IOException { log.info("Attempting operation..."); // 这里抛出一个可能导致重试的异常 throw new IOException("Operation failed!"); } //定义一个 @Recover 方法来处理所有重试失败后的恢复逻辑 @Recover public void recover(IOException e) { log.info("All retries failed. Recovering from exception: " + e.getMessage()); // 执行恢复逻辑,如记录日志、通知用户、清理资源等 } }

(3)解释

  • performOperation 方法使用了@Retryable注解,指定了在遇到 IOException 时会进行最多 3 次重试,每次重试之间间隔 2000 毫秒。
  • 如果 performOperation 方法在所有重试尝试后仍然抛出 IOException,此时@Retryable注解中的 recover 属性指定的方法(即 recover 方法)将被调用。recover 方法处理这些失败后的恢复操作,比如记录错误信息或通知用户。

(4)输出结果如下:

2024-09-09 23:23:49.282 INFO 2668 --- [nio-8080-exec-2] c.e.m.s.impl.AnnotationTestServiceImpl : Attempting operation... 2024-09-09 23:23:51.292 INFO 2668 --- [nio-8080-exec-2] c.e.m.s.impl.AnnotationTestServiceImpl : Attempting operation... 2024-09-09 23:23:53.294 INFO 2668 --- [nio-8080-exec-2] c.e.m.s.impl.AnnotationTestServiceImpl : Attempting operation... 2024-09-09 23:23:53.295 INFO 2668 --- [nio-8080-exec-2] c.e.m.s.impl.AnnotationTestServiceImpl : All retries failed. Recovering from exception: Operation failed!

注:上面只展示了核心代码,并未展示其它代码(例如 Controller 层代码)。

4.2.两者对应关系

(1)@Retryable注解与@Recover注解的对应关系如下:

  • 异常匹配:@Recover 注解的方法的参数类型必须与 @Retryable 注解的方法抛出的异常类型一致。这样,Spring 能够将最终失败的异常传递到对应的 @Recover 方法中(否则会提示报错)。在上述例子中,performOperation 方法抛出的异常类型与 recover 方法的参数类型均为IOException
  • 方法名和数量:每个 @Retryable 注解的方法通常对应一个 @Recover 方法。如果有多个 @Retryable 方法,则每个方法需要有一个匹配的 @Recover 方法来处理相应的异常。

(2)recover 属性可省略:以上述例子来说,只要 @Recover 注解的方法的参数类型与 @Retryable 注解的方法抛出的异常类型一致,即使不设置 recover 属性,当 performOperation 方法重试全部失败后,recover 方法也会被执行

5.其他注意事项

(1)使用@Retryable注解时,需要注意以下几点:

  • 异常类型:确保指定的valueincluderetryFor属性中的异常类型与你的代码实际抛出的异常一致。
  • 性能影响:频繁重试可能会对系统性能产生影响,因此合理配置maxAttemptsbackoff
  • 幂等性:确保被重试的方法是幂等的,即多次执行不会引起副作用。
  • 超时设置:配置合理的重试超时时间和间隔,避免重试导致的长时间等待。
  • 正确配置 backoff:使用合理的delaymultiplier,以避免过于频繁的重试或间隔过长。

(2)@Retryable 注解与 @Recover 注解配合使用,需要注意:一般建议一个@Retryable注解方法对应一个@Recover注解方法,并且通过设置 @Retryable 注解中的 recover 属性来指定对应的恢复方法。因为当多个@Recover注解方法的参数类型与一个@Retryable注解方法抛出的异常类型相同时,可能难会产生一些不确定的问题。

(3)例如,下面的代码并未设置@Retryable注解的 recover 属性,那么按照上面的对应规则,recover1 方法和 recover2 方法均为 performOperation 方法的恢复方法,那么当 performOperation 方法全部重试失败后,到底哪个恢复方法会执行呢?还是都执行呢?

@Slf4j @Service public class AnnotationTestServiceImpl implements AnnotationTestService { //定义一个需要重试的方法 @Override @Retryable(value = IOException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000)) public void performOperation() throws IOException { log.info("Attempting operation..."); // 这里抛出一个可能导致重试的异常 throw new IOException("Operation failed!"); } //定义一个 @Recover 方法来处理所有重试失败后的恢复逻辑 @Recover public void recover2(IOException e) { log.info("All retries failed. Recovering from exception2: " + e.getMessage()); // 执行恢复逻辑,如记录日志、通知用户、清理资源等 } //定义一个 @Recover 方法来处理所有重试失败后的恢复逻辑 @Recover public void recover1(IOException e) { log.info("All retries failed. Recovering from exception1: " + e.getMessage()); // 执行恢复逻辑,如记录日志、通知用户、清理资源等 } }

测试后的结果如下:

显然是 recover1 方法生效了,而 recover2 方法并未生效。具体原因,本人并未深入了解(本人猜测与方法名的字典顺序有关,排在前面的先执行),有明白原因的读者可以在评论区留言。

那如果在@Retryable注解中设置属性 recover = “recover2”,结果则会与上面相反,如下图所示:

(4)所以为了避免出现上述情况,这里建议当 @Retryable 注解与 @Recover 注解配合使用时,最好通过 @Retryable 注解的 recover 属性来设置对应的恢复方法,并且 @Recover 注解的方法的参数类型必须与 @Retryable 注解的方法抛出的异常类型保持一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1142291.shtml

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

相关文章

HY-MT1.5多引擎对比:性能与质量评测

HY-MT1.5多引擎对比&#xff1a;性能与质量评测 1. 引言 随着全球化进程的加速&#xff0c;高质量、低延迟的机器翻译需求日益增长。在这一背景下&#xff0c;腾讯开源了混元翻译大模型 HY-MT1.5 系列&#xff0c;包含两个核心版本&#xff1a;HY-MT1.5-1.8B 和 HY-MT1.5-7B。…

Spring 核心技术解析【纯干货版】- Ⅶ:Spring 切面编程模块 Spring-Instrument 模块精讲

随着 Java 技术栈的不断发展&#xff0c;Spring 框架在应用开发中占据了举足轻重的地位。Spring 提供了丰富的模块来支持不同的应用场景&#xff0c;其中 spring-instrument 模块作为其中的一部分&#xff0c;提供了强大的类加载器增强功能。该模块通过字节码操作和类加载期织入…

ros2(jazzy)多节点运行在同一个进程范例(对标ros1的nodelet)

以下是一个完整的 ROS2 节点动态组合&#xff08;Composable Nodes&#xff09; 开发案例&#xff0c;涵盖 编译时组合 和 运行时组合 两种方式&#xff0c;并包含 参数传递 和 命名空间重映射 等高级功能。 案例目标 实现一个 Talker&#xff08;发布者&#xff09; 和 Liste…

【C++】2.7 哈希表及其实现

二次探测&#xff1a;由于直接这么探测&#xff0c;要是数据堆积那么效率较低 因此&#xff0c;可以将i改成-i方&#xff0c;让数据更加分散 其它都一样&#xff0c;将hash0 i改为hashi*i即可(2) 双重散列法 由于二次探测在冲突时-的值时一样的&#xff0c;依旧不能解决堆积问…

PDF-Extract-Kit错误排查:解决‘上传文件无反应‘问题

PDF-Extract-Kit错误排查&#xff1a;解决上传文件无反应问题 1. 引言 在使用PDF-Extract-Kit这一由科哥二次开发构建的PDF智能提取工具箱时&#xff0c;用户可能会遇到“上传文件后无反应”的典型问题。该问题表现为&#xff1a;用户成功启动WebUI服务并访问页面后&#xff…

HY-MT1.5部署实战:5分钟搭建企业级翻译系统

HY-MT1.5部署实战&#xff1a;5分钟搭建企业级翻译系统 在AI驱动的全球化浪潮中&#xff0c;高质量、低延迟的机器翻译能力已成为企业出海、跨语言协作的核心基础设施。腾讯近期开源的混元翻译大模型HY-MT1.5系列&#xff0c;凭借其卓越的翻译质量与灵活的部署能力&#xff0c…

操作指南:Proteus8.16下载安装教程配合Keil联合仿真

手把手搭建嵌入式虚拟实验室&#xff1a;Proteus 8.16 Keil 联合仿真实战指南 你有没有过这样的经历&#xff1f; 写好一段51单片机代码&#xff0c;烧进芯片却发现LED不闪&#xff1b;反复检查电路&#xff0c;换了几块板子才意识到是定时器配置错了。等改完再烧录&#xf…

Spring+Quartz实现定时任务的配置方法

<?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns:context"http://www.springframework.org/schema/c…

腾讯HY-MT1.5-1.8B性能测试:小模型大作为实战分析

腾讯HY-MT1.5-1.8B性能测试&#xff1a;小模型大作为实战分析 1. 引言&#xff1a;小参数&#xff0c;大能力——腾讯混元翻译模型的轻量化突破 随着多语言交流需求的爆发式增长&#xff0c;高质量、低延迟的机器翻译系统成为智能应用的核心组件。然而&#xff0c;传统大模型虽…

Spring 过滤器:OncePerRequestFilter 应用详解

在Web应用中&#xff0c;过滤器&#xff08;Filter&#xff09;是一个强大的工具&#xff0c;它可以在请求到达目标资源之前或响应返回客户端之前对请求或响应进行拦截和处理。然而&#xff0c;在某些情况下&#xff0c;我们可能希望确保过滤器逻辑在一次完整的HTTP请求中仅执行…

PDF-Extract-Kit部署教程:跨平台部署解决方案

PDF-Extract-Kit部署教程&#xff1a;跨平台部署解决方案 1. 引言 1.1 技术背景与学习目标 PDF-Extract-Kit 是一款由开发者“科哥”二次开发构建的PDF智能提取工具箱&#xff0c;集成了布局检测、公式识别、OCR文字提取、表格解析等核心功能&#xff0c;广泛适用于学术论文…

HY-MT1.5术语干预SDK开发:自定义术语库集成

HY-MT1.5术语干预SDK开发&#xff1a;自定义术语库集成 1. 引言 随着全球化进程的加速&#xff0c;高质量、可定制化的机器翻译需求日益增长。尤其是在专业领域&#xff08;如法律、医疗、金融&#xff09;和多语言混合场景中&#xff0c;通用翻译模型往往难以满足对术语一致…

Spring 的三种注入方式?

1. 实例的注入方式 首先来看看 Spring 中的实例该如何注入&#xff0c;总结起来&#xff0c;无非三种&#xff1a;属性注入set 方法注入构造方法注入我们分别来看下。 1.1 属性注入 属性注入是大家最为常见也是使用最多的一种注入方式了&#xff0c;代码如下&#xff1a; Servi…

深度剖析ST7789初始化序列:适合初学的理解方式

点亮第一帧&#xff1a;拆解ST7789初始化背后的工程逻辑你有没有遇到过这样的场景&#xff1f;硬件接好了&#xff0c;代码烧进去了&#xff0c;LVGL界面也写得漂漂亮亮——结果屏幕一动不动&#xff0c;黑屏、白屏、花屏轮番上演。反复检查接线无误&#xff0c;SPI通信也有波形…

PDF-Extract-Kit实战案例:智能文档检索系统

PDF-Extract-Kit实战案例&#xff1a;智能文档检索系统 1. 引言 在科研、教育和企业办公场景中&#xff0c;PDF 文档作为知识传递的核心载体&#xff0c;往往包含大量结构化信息——如文字、表格、数学公式和图像。然而&#xff0c;传统方式难以高效提取这些内容并进行二次利…

BRAM在图像处理缓存中的实现:完整示例解析

BRAM在图像处理缓存中的实战设计&#xff1a;从原理到可综合代码你有没有遇到过这样的问题——明明FPGA的逻辑资源还很充裕&#xff0c;但图像处理流水线却频频卡顿&#xff1f;像素流断了、卷积核等数据、边缘检测结果延迟飙升……最终发现&#xff0c;瓶颈不在算法&#xff0…

HY-MT1.5性能对比:与Google翻译API实测数据

HY-MT1.5性能对比&#xff1a;与Google翻译API实测数据 在多语言交流日益频繁的今天&#xff0c;高质量、低延迟的机器翻译模型成为跨语言沟通的核心基础设施。近年来&#xff0c;随着大模型技术的快速发展&#xff0c;开源翻译模型逐渐具备了与商业API相媲美的能力。腾讯近期…

PDF智能提取工具箱实战:手写公式转LaTeX完整步骤

PDF智能提取工具箱实战&#xff1a;手写公式转LaTeX完整步骤 1. 引言&#xff1a;从扫描文档到结构化数据的智能化跃迁 在科研、教学和工程实践中&#xff0c;PDF文档中常包含大量手写或印刷体数学公式、表格和文本内容。传统方式下&#xff0c;将这些非结构化信息转化为可编…

基于深度学习 YOLOv8➕pyqt5的西红柿成熟度检测系统

基于深度学习 YOLOv8➕pyqt5的西红柿成熟度检测系统&#xff0c; 完整源码源文件已标注的数据集训练好的模型环境配置教程程序运行说明文档 可以替换自己训练的模型&#xff0c;实现检测目标自定义 blog.csdnimg.cn/direct/31c61653310648458126c961a01fd682.png) 以下文章及示…

PDF-Extract-Kit快速上手:10分钟完成第一个PDF解析项目

PDF-Extract-Kit快速上手&#xff1a;10分钟完成第一个PDF解析项目 1. 引言 在科研、教育和办公场景中&#xff0c;PDF文档常包含大量结构化信息——如公式、表格、图文混排内容。然而&#xff0c;传统方式难以高效提取这些元素&#xff0c;尤其是数学公式和复杂表格的数字化…