You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带@Scheduled的@Retryable方法对应的@Recover方法未触发问题排查

解决@Recover方法未随@Retryable触发的问题

我懂你这种查了一堆相关问题还是卡壳的感觉,咱们来一步步拆解你的代码里的问题,帮你让@Recover正常跑起来。

最核心的问题:@Scheduled和@Retryable的代理冲突

Spring的@Scheduled和@Retryable都是靠动态代理实现的,但如果把这两个注解加在同一个方法上,就会出现代理逻辑冲突——@Scheduled的代理会先接管方法执行,导致@Retryable的重试逻辑根本没被触发,那@Recover自然也不会执行。

解决方法:拆分定时任务和重试逻辑

把定时任务的调用和带重试的方法分开写,让重试逻辑在单独的方法里执行,这样两个代理就能各司其职了:

@Service
public class MyRetryingService {
    @Scheduled(fixedRate = 10 * 1000)
    public void scheduledTransferTask() {
        // 调用带重试逻辑的方法
        transferData();
    }

    @Retryable(backoff = @Backoff(delay = 100, maxDelay = 101), maxAttempts = 3)
    public void transferData() {
        throw new IllegalArgumentException();
    }

    @Recover
    public void recover(IllegalArgumentException exception) {
        System.out.println("Recovering from a service down");
    }
}

还要检查这两个配置细节

1. 确保Spring Retry的依赖和启用配置都到位

  • 确认项目里已经引入了Spring Retry的依赖(比如Maven的spring-retry和spring-aspects)
  • 在你的配置类上加上@EnableRetry和@EnableScheduling注解,不然Spring根本不会识别重试和定时任务的逻辑:
@Configuration
@EnableRetry
@EnableScheduling
public class AppConfig {
    // 其他配置内容
}

2. 核对@Recover方法的签名匹配

虽然你的@Recover方法参数看起来没问题,但还是要确认:

  • @Recover方法的参数必须和@Retryable方法抛出的异常完全匹配(你的IllegalArgumentException是对的)
  • @Recover方法的返回值要和@Retryable方法一致(都是void,这点没问题)
  • 两个方法必须在同一个类中(你已经满足)

最后再验证一下

做完上面的修改后,启动项目,当transferData方法抛出异常时,Spring会重试3次,之后就会触发recover方法打印日志了。

内容的提问来源于stack exchange,提问作者Kamal Joshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:43:08