如何为指定@Retryable方法匹配对应的@Recover恢复方法?
问题根因
Spring Retry 中@Recover注解的默认匹配逻辑优先按「返回值类型 + 异常参数类型 + 入参列表」三者匹配,当多个恢复方法的这三个属性完全一致时,框架会按方法加载的顺序选择第一个匹配到的恢复方法,因此会出现method3重试失败后调用了method1的恢复方法的问题。
解决方案
方案1:通过@Retryable的recover属性显式绑定(最推荐)
Spring Retry 1.3及以上版本已经支持在@Retryable注解中通过recover属性直接指定对应恢复方法的方法名,强制绑定重试方法和恢复方法的对应关系,无需修改方法签名,也不用替换为RetryTemplate。
示例代码修改如下:
// 显式绑定method1对应的恢复方法 @Retryable(recover = "method1Recovery") public boolean method1(String arg1) { // do something } @Recover public boolean method1Recovery(Exception e, String arg1) { //do something } // 显式绑定method3对应的恢复方法 @Retryable(recover = "method3Recovery") public boolean method3(String arg1) { // do something } @Recover public boolean method3Recovery(Exception e, String arg1) { //do something }
使用注意:
- 重试方法和对应的恢复方法必须在同一个类中
- 恢复方法的方法名要和
recover属性的取值完全一致 - 恢复方法的返回类型必须和重试方法的返回类型兼容,异常参数必须是重试方法抛出的异常类型或其父类,除第一个异常参数外的入参顺序要和重试方法的入参顺序完全一致
方案2:自定义异常区分匹配逻辑
如果使用的Spring Retry版本低于1.3,不支持recover属性,可以给不同的重试方法声明抛出不同的自定义异常,让恢复方法的异常参数和对应重试方法抛出的异常一一对应,即可避免匹配错误。
示例:
// 为不同方法定义独立的自定义异常 public class Method1Exception extends RuntimeException{} public class Method3Exception extends RuntimeException{} @Retryable public boolean method1(String arg1) throws Method1Exception { // 业务逻辑执行失败时抛出Method1Exception } @Recover public boolean method1Recovery(Method1Exception e, String arg1) { // 仅匹配Method1Exception对应的重试失败场景 } @Retryable public boolean method3(String arg1) throws Method3Exception { // 业务逻辑执行失败时抛出Method3Exception } @Recover public boolean method3Recovery(Method3Exception e, String arg1) { // 仅匹配Method3Exception对应的重试失败场景 }
关于RetryTemplate的疑问
显式使用RetryTemplate指定RetryCallback和RecoveryCallback并不是唯一的实现方式,上述两种基于注解的方案都可以实现恢复方法的精准匹配,只有当你需要非常灵活的重试、恢复自定义逻辑时,才需要使用RetryTemplate手动编码实现。
内容的提问来源于stack exchange,提问作者shazwashere
相关产品推荐
相关产品推荐

