一、解释下 springboot中 @Retryable 注解
@Retryable
注解是 Spring Retry 模块提供的一个注解,用于在方法调用失败时自动重试。它可以帮助开发者处理临时性错误,比如网络故障、服务不可用等场景。以下是对 @Retryable
注解的详细解释:
- 功能:当方法执行抛出指定异常时,自动重试该方法。
- 配置:
maxAttempts
:最大重试次数,默认为 3。backoff
:重试之间的等待时间,可以设置延迟策略。include
和exclude
:指定哪些异常会触发重试。
- 用法:通常在服务层的方法上使用,确保在遇到可恢复的异常时,能够自动重试。
伪代码步骤
- 导入 Spring Retry 依赖。
- 在应用程序中启用 Spring Retry。
- 在方法上使用
@Retryable
注解,指定重试参数。 - 处理可能的异常。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { CustomException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void myMethod() throws CustomException {
// 业务逻辑
// 可能会抛出 CustomException
}
@Recover
public void recover(CustomException e) {
// 处理最终失败的逻辑
}
}
二、配合 @Recover 能达到什么效果
@Recover
注解与 @Retryable
注解结合使用时,可以实现更好的异常处理和恢复机制。以下是它的效果和用法:
效果
- 异常处理:当
@Retryable
注解的方法在所有重试后仍然失败时,@Recover
注解的方法将被调用,可以在这里处理最终失败的逻辑。 - 分离逻辑:通过
@Recover
方法,可以将重试逻辑与失败后的处理逻辑分开,使代码更加清晰和可维护。 - 自定义恢复:可以根据不同的异常类型定义不同的恢复方法,提供灵活的错误处理策略。
伪代码步骤
- 定义一个带有
@Recover
注解的方法,与@Retryable
方法在同一类中。 @Recover
方法的参数需与@Retryable
方法的异常类型一致。- 在
@Recover
方法中实现失败后的处理逻辑。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { CustomException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void myMethod() throws CustomException {
// 业务逻辑
// 可能会抛出 CustomException
}
@Recover
public void recover(CustomException e) {
// 处理最终失败的逻辑,例如记录日志或发送通知
System.out.println("Method failed after retries: " + e.getMessage());
}
}
三、能在同一个类中添加多个重试方法吗?
是的,可以在同一个类中添加多个重试方法。每个方法都可以使用 @Retryable
注解,且可以根据需求配置不同的重试策略和异常类型。每个 @Retryable
方法可以有自己的重试逻辑以及对应的 @Recover
方法。
伪代码步骤
- 在同一类中定义多个方法,并为每个方法使用
@Retryable
注解。 - 为每个重试方法定义对应的
@Recover
方法,以处理不同的异常。 - 可以为每个重试方法配置不同的参数,如最大重试次数和延迟时间。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { CustomException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws CustomException {
// 业务逻辑,可能抛出 CustomException
}
@Recover
public void recoverMethodA(CustomException e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Retryable(value = { AnotherException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws AnotherException {
// 业务逻辑,可能抛出 AnotherException
}
@Recover
public void recoverMethodB(AnotherException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
在这个示例中,MyService
类中有两个重试方法 methodA
和 methodB
,它们分别处理不同的异常,并有各自的恢复逻辑。
四、如果一个类中有多个@Retryable 和 @Recover,这俩注解如何对应上
在一个类中有多个 @Retryable
和 @Recover
注解时,它们会通过方法的参数类型和方法名称来对应。具体来说,每个 @Recover
方法的参数类型必须与其对应的 @Retryable
方法抛出的异常类型相匹配。以下是详细说明:
对应规则
- 异常类型匹配:
@Recover
方法的第一个参数必须是与@Retryable
方法中抛出的异常类型相同的异常类型。 - 方法名称:虽然方法名称不是匹配的必要条件,但为了代码可读性,通常建议使用描述性的方法名称,例如
recoverMethodA
对应methodA
。 - 可选参数:
@Recover
方法可以有其他参数(如原方法的参数),这使得在恢复逻辑中可以获取到原始方法的输入。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { CustomException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws CustomException {
// 业务逻辑,可能抛出 CustomException
}
@Recover
public void recoverMethodA(CustomException e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Retryable(value = { AnotherException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws AnotherException {
// 业务逻辑,可能抛出 AnotherException
}
@Recover
public void recoverMethodB(AnotherException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
在这个示例中:
methodA
抛出CustomException
,对应的恢复方法是recoverMethodA
。methodB
抛出AnotherException
,对应的恢复方法是recoverMethodB
。
这样通过异常类型和方法名称的匹配,Spring 能够正确地将 @Retryable
和 @Recover
注解对应起来。
五、如果a方法抛出Exception ,b方法抛出 CustomException ,这时候该如何对应
在这种情况下,如果一个方法(a
方法)抛出 Exception
,而另一个方法(b
方法)抛出 CustomException
,你可以在 b
方法的 @Recover
注解中处理 Exception
类型的异常。这样可以实现更通用的异常处理逻辑。
对应规则
- 异常层次结构:
CustomException
是Exception
的子类,因此@Recover
方法可以接受Exception
。 - 方法参数:你可以为
@Recover
方法定义一个接受Exception
的参数,以及其他必要的参数(如原始方法的参数)。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
// 业务逻辑,可能抛出 Exception
throw new Exception("Error in methodA");
}
@Retryable(value = { CustomException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws CustomException {
// 业务逻辑,可能抛出 CustomException
throw new CustomException("Error in methodB");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Recover
public void recoverMethodB(CustomException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
关键点
methodA
抛出Exception
,对应的恢复方法recoverMethodA
接受Exception
类型的参数。methodB
抛出CustomException
,对应的恢复方法recoverMethodB
接受CustomException
类型的参数。- 如果
methodA
在重试后仍然失败,recoverMethodA
将被调用处理Exception
。 methodB
的重试逻辑专门处理CustomException
,并在所有重试后调用recoverMethodB
。
这样设计使得你可以在一个类中处理多种异常类型,并根据不同的异常提供不同的恢复处理逻辑。
六、按照规则Exception 包含CustomException,像上面的写法a重试方法会捕捉到b方法吗
在 Spring Retry 中,@Retryable
注解的方法不会捕获其他方法的异常。每个 @Retryable
注解的方法都是独立的,它们的重试逻辑只会针对自身抛出的异常进行处理。因此,methodA
重试时不会影响到 methodB
,反之亦然。
关键点
- 独立性:每个
@Retryable
方法的异常处理是独立的。methodA
的重试逻辑只针对其自身抛出的Exception
,而不会捕获methodB
抛出的CustomException
。 - 异常层次:虽然
CustomException
是Exception
的子类,但在@Retryable
的上下文中,methodA
和methodB
是分开的。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
// 业务逻辑,可能抛出 Exception
throw new Exception("Error in methodA");
}
@Retryable(value = { CustomException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws CustomException {
// 业务逻辑,可能抛出 CustomException
throw new CustomException("Error in methodB");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Recover
public void recoverMethodB(CustomException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
总结
methodA
和methodB
的重试逻辑是独立的。methodA
抛出的Exception
不会被methodB
的@Retryable
逻辑捕获,反之亦然。- 每个方法的
@Recover
逻辑只处理该方法定义的异常类型。
七、如果b方法抛出BusException,这时会被a的重试方法捕捉到吗
在 Spring Retry 中,methodA
的重试逻辑不会捕获 methodB
抛出的 BusException
。每个 @Retryable
方法的异常处理是相互独立的。
关键点
- 方法独立性:每个
@Retryable
注解的方法都只处理自身抛出的异常。methodA
的重试逻辑只会处理它自己抛出的异常(如Exception
),而不会处理methodB
抛出的BusException
。 - 异常传播:如果
methodA
调用了methodB
,并且methodB
抛出了BusException
,那么methodA
需要显式处理这个异常(如使用try-catch
语句),否则该异常将导致methodA
失败。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
try {
methodB(); // 调用 methodB
} catch (BusException e) {
// 处理 BusException 或者重新抛出
throw new Exception("Caught BusException from methodB", e);
}
}
@Retryable(value = { BusException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodB");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Recover
public void recoverMethodB(BusException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
总结
methodA
不会自动捕获methodB
抛出的BusException
,除非它显式调用methodB
并在try-catch
块中处理该异常。- 如果
methodA
捕获并重新抛出BusException
,则可以通过其@Retryable
注解的配置进行重试。
八、就是说,如果a方法抛出了CustomException 的时候,不会触发重试机制吗
是的,如果 methodA
抛出了 CustomException
,并且 methodA
的 @Retryable
注解没有将 CustomException
包含在重试的异常类型列表中,则不会触发重试机制。
关键点
- 异常类型匹配:
@Retryable
注解指定的异常类型决定了哪些异常会触发重试。如果methodA
抛出的异常不在@Retryable
注解的value
属性中,重试机制将不会被触发。 - 自定义异常:如果
methodA
抛出CustomException
,而@Retryable
只配置了重试其他异常(如Exception
),则该异常不会导致重试。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws CustomException {
// 业务逻辑,可能抛出 CustomException
throw new CustomException("Error in methodA");
}
@Retryable(value = { BusException.class }, maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void methodB() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodB");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
@Recover
public void recoverMethodB(BusException e) {
// 处理 methodB 最终失败的逻辑
System.out.println("methodB failed after retries: " + e.getMessage());
}
}
结论
- 在上面的示例中,
methodA
抛出的CustomException
不会触发重试,因为@Retryable
只配置了对Exception
的重试。 - 要使
CustomException
触发重试,需要将其添加到@Retryable
的value
属性中,例如@Retryable(value = { CustomException.class, Exception.class })
。这样,如果methodA
抛出CustomException
,则会触发重试机制。
九、如果a指定了Exception,但是没有指定CustomException,执行方法中的代码时抛出了CustomException,这时会触发重试机制吗
如果 methodA
的 @Retryable
注解指定了 Exception
作为重试的异常类型,但没有指定 CustomException
,那么当 methodA
中的代码抛出 CustomException
时,将不会触发重试机制。
关键点
- 重试机制依据:
@Retryable
注解的value
属性指定了哪些异常会触发重试。如果抛出的异常不在这个列表中,则重试机制不会被触发。 - 异常层次:
CustomException
是Exception
的子类,但在@Retryable
的上下文中,只有被明确列出的异常才会导致重试。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
// 业务逻辑,可能抛出 CustomException
throw new CustomException("Error in methodA"); // 这里抛出 CustomException
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
}
结论
- 在上面的示例中,如果
methodA
抛出了CustomException
,由于@Retryable
只指定了Exception
,因此不会触发重试机制。 - 要使
CustomException
触发重试,必须将其添加到@Retryable
的value
属性中,例如:@Retryable(value = { CustomException.class, Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
- 这样配置后,如果
methodA
抛出CustomException
,则会触发重试机制。
十、果a没有指定@Retryable value中的异常,但是在方法加上了throws Exception,这时a抛出BusinessException,会触发重试机制吗?@Recover的方法参数使用了Exception,这时会触发@Recover方法吗?
在这种情况下,如果 methodA
没有在 @Retryable
的 value
属性中指定任何异常类型,但方法签名中使用了 throws Exception
,则行为如下:
- 触发重试机制:如果
methodA
抛出BusinessException
,由于@Retryable
没有指定任何异常类型,重试机制不会被触发。@Retryable
需要明确指定异常类型,才能对此类异常进行重试。 - 调用 @Recover 方法:由于重试机制没有被触发,
@Recover
方法也不会被调用。@Recover
方法只有在重试机制成功完成且仍然抛出指定的异常时才会被调用。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
// 没有指定 @Retryable 的 value
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
// 业务逻辑,抛出 BusinessException
throw new BusinessException("Error in methodA");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
}
结论
- 在上述示例中,
methodA
抛出的BusinessException
不会触发重试机制,因为@Retryable
没有指定要重试的异常类型。 - 由于没有触发重试,
@Recover
方法也不会被调用。
解决方案
如果希望 BusinessException
触发重试,需要在 @Retryable
中指定它,例如:
@Retryable(value = { BusinessException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
这样配置后,如果 methodA
抛出 BusinessException
,则会触发重试机制,并在重试失败后调用 @Recover
方法。
十一、可以我看源码说明,如果不指定,则重试所有异常
在 Spring Retry 的实现中,如果在 @Retryable
注解中没有指定 value
属性,默认情况下会重试所有未被捕获的异常。这是因为 @Retryable
的行为是基于 RetryTemplate
的,而 RetryTemplate
会捕获所有未处理的异常。
源码说明
在 Spring Retry 的源码中,@Retryable
的行为主要由 RetryTemplate
和 RetryPolicy
决定。默认情况下,RetryTemplate
会使用 SimpleRetryPolicy
,该策略会重试所有异常。
关键代码
以下是 RetryTemplate
和 SimpleRetryPolicy
中的相关部分的简化示例:
public class RetryTemplate {
private RetryPolicy retryPolicy;
public void execute(RetryCallback<T> callback) {
// 省略其他代码
while (true) {
try {
return callback.doWithRetry(context);
} catch (Throwable e) {
if (!retryPolicy.canRetry(context)) {
throw e; // 如果不可以重试,则抛出异常
}
}
}
}
}
public class SimpleRetryPolicy implements RetryPolicy {
@Override
public boolean canRetry(RetryContext context) {
// 如果没有指定异常,则允许重试所有异常
return true;
}
}
结论
- 如果
@Retryable
没有指定value
,则默认会重试所有未捕获的异常。 - 这意味着在方法中抛出的任何异常(包括
BusinessException
)都会触发重试机制。 - 当重试次数用尽后,
@Recover
方法会被调用(如果定义了)。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
// 没有指定 @Retryable 的 value,默认重试所有异常
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws Exception {
// 业务逻辑,抛出 BusinessException
throw new BusinessException("Error in methodA");
}
@Recover
public void recoverMethodA(Exception e) {
// 处理 methodA 最终失败的逻辑
System.out.println("methodA failed after retries: " + e.getMessage());
}
}
在这个示例中,如果 methodA
抛出 BusinessException
,将会触发重试机制,并在重试失败后调用 @Recover
方法。
十二、现在有三个方法value都是指定BusException,这时@Recover该如何对应上
如果你有三个方法,它们的 @Retryable
注解的 value
都指定为 BusException
,那么你可以为每个方法定义一个对应的 @Recover
方法。每个 @Recover
方法的参数类型应该与对应的 @Retryable
方法抛出的异常类型一致。
关键点
- 对应关系:每个
@Recover
方法需要与特定的@Retryable
方法相对应。@Recover
方法的参数类型应与@Retryable
方法中抛出的异常类型一致。 - 方法重载:如果需要,你可以根据不同的方法名称来定义不同的
@Recover
方法,或者通过方法签名区分。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodA");
}
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodB() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodB");
}
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodC() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodC");
}
// 对应 methodA 的 @Recover 方法
@Recover
public void recoverMethodA(BusException e) {
System.out.println("methodA failed after retries: " + e.getMessage());
}
// 对应 methodB 的 @Recover 方法
@Recover
public void recoverMethodB(BusException e) {
System.out.println("methodB failed after retries: " + e.getMessage());
}
// 对应 methodC 的 @Recover 方法
@Recover
public void recoverMethodC(BusException e) {
System.out.println("methodC failed after retries: " + e.getMessage());
}
}
结论
- 在上述示例中,
methodA
、methodB
和methodC
都指定了重试BusException
。 - 每个方法都有一个对应的
@Recover
方法,能够处理其各自的失败情况。 - 通过这种方式,你可以为不同的方法提供特定的恢复逻辑。
十三、抛出的异常都一致,三个@Recover如何找到对应的@Retryable方法
在 Spring Retry 中,当抛出的异常类型一致时,@Recover
方法的匹配是通过方法的名称来区分的。每个 @Recover
方法的名称应该与其对应的 @Retryable
方法名称相匹配。Spring 会根据 @Recover
方法的名称来确定它对应的 @Retryable
方法。
关键点
- 方法命名:
@Recover
方法的名称必须与其对应的@Retryable
方法的名称一致,或者通过方法参数的类型来匹配。 - 参数类型:
@Recover
方法的参数类型必须与@Retryable
方法抛出的异常类型一致。
示例代码
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodA() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodA");
}
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodB() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodB");
}
@Retryable(value = { BusException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public void methodC() throws BusException {
// 业务逻辑,可能抛出 BusException
throw new BusException("Error in methodC");
}
// 对应 methodA 的 @Recover 方法
@Recover
public void recoverMethodA(BusException e) {
System.out.println("methodA failed after retries: " + e.getMessage());
}
// 对应 methodB 的 @Recover 方法
@Recover
public void recoverMethodB(BusException e) {
System.out.println("methodB failed after retries: " + e.getMessage());
}
// 对应 methodC 的 @Recover 方法
@Recover
public void recoverMethodC(BusException e) {
System.out.println("methodC failed after retries: " + e.getMessage());
}
}
结论
- 在上面的示例中,
methodA
、methodB
和methodC
都重试BusException
。 - 每个方法都有一个
@Recover
方法,名称分别为recoverMethodA
、recoverMethodB
和recoverMethodC
,这样 Spring 就能根据方法名称找到对应的@Retryable
方法。 - 通过这种方式,可以确保每个方法的恢复逻辑是相互独立的。
评论区