Spring Boot中@Scheduled与@Retryable联用重试机制未触发问题排查
Spring Boot中@Scheduled搭配@Retryable不生效的问题排查与解决
根因分析
- 方法修饰符为protected导致AOP切面拦截失败
@Retryable基于Spring AOP动态代理实现,默认JDK动态代理仅支持public方法拦截,即使用CGLIB代理,未显式配置的情况下也无法拦截protected方法,重试切面无法触发。 - 未指定重试异常类型,默认不支持检查异常重试
@Retryable默认仅对RuntimeException、Error类型的异常触发重试,你代码中声明抛出的JobExecutionAlreadyRunningException等均为检查型异常,默认不在重试触发范围内。 - Spring Batch任务内部异常未透出到外层方法
如果任务Step内部的异常被Spring Batch自带的容错机制(skip、内置重试等)捕获处理,没有透出到simpleJobLauncher.run()方法外层,runJob不会抛出异常,@Retryable无法感知到异常触发重试。
修复方案
- 将
runJob方法的修饰符从protected改为public,符合Spring AOP的代理规则 - 在@Retryable注解中显式声明需要重试的异常类型,覆盖所有可能抛出的检查异常
- 确认Spring Batch任务的异常可以正常透出到
runJob方法外层,没有被内部容错逻辑完全吞掉
修复后的代码示例:
@Component public class JobRunnerStats { @Scheduled(cron = "0 0/2 * ? * *") @Retryable( maxAttempts = 10, backoff = @Backoff(delay = 1000), include = { JobExecutionAlreadyRunningException.class, JobRestartException.class, JobInstanceAlreadyCompleteException.class, JobParametersInvalidException.class } ) public JobExecution runJob() throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException { // 原有业务逻辑不变 JobParameters jobParameters = null; if (this.jobParameters == null) { jobParameters = buildJobParameters(null); } else { jobParameters = this.jobParameters; this.jobParameters = null; } return simpleJobLauncher.run(this.jobStats, jobParameters); } }
内容的提问来源于stack exchange,提问作者Joe Taras
相关产品推荐
相关产品推荐

