Spring中方法A失败后执行方法B再重试A的实现方案
Spring框架下的规范实现方案
你提到的需求完全可以通过Spring Retry实现,可能之前没注意到它的扩展能力。下面是几种规范的实现方式:
1. 基于RetryTemplate + RetryListener(推荐)
通过RetryTemplate配置重试规则,结合RetryListener在重试前执行方法B的补偿操作:
@Service public class RetryDemoService { private final RetryTemplate retryTemplate; public RetryDemoService(RetryTemplate retryTemplate) { this.retryTemplate = retryTemplate; } public void executeTask() { try { retryTemplate.execute(retryContext -> { // 执行目标方法A methodA(); return null; }); } catch (Exception e) { // 两次执行(初始+重试)都失败后的最终处理 } } // 配置RetryTemplate Bean @Bean public RetryTemplate customRetryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); // 设置重试次数:初始执行1次 + 重试1次,总共2次尝试 SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(2); // 添加重试监听器,在第一次失败后执行方法B retryTemplate.registerRetryListener(new RetryListener() { @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { return true; } @Override public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {} @Override public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { // retryCount=1表示第一次执行失败,即将触发重试 if (context.getRetryCount() == 1) { methodB(); } } }); retryTemplate.setRetryPolicy(retryPolicy); return retryTemplate; } private void methodA() { // 你的业务逻辑,可能抛出异常 } private void methodB() { // 方法A失败后的补偿操作 } }
2. 注解式实现:@Retryable + 自定义拦截器
如果偏好注解方式,可以通过自定义重试拦截器嵌入补偿逻辑:
@Service public class AnnotationRetryService { // 指定自定义拦截器,设置最大尝试次数为2 @Retryable(maxAttempts = 2, interceptor = "compensateRetryInterceptor") public void methodA() { // 业务逻辑 } public void methodB() { // 补偿操作 } @Bean public RetryOperationsInterceptor compensateRetryInterceptor() { RetryOperationsInterceptor interceptor = new RetryOperationsInterceptor(); RetryTemplate retryTemplate = new RetryTemplate(); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(2); retryTemplate.registerRetryListener(new RetryListener() { @Override public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { if (context.getRetryCount() == 1) { methodB(); } } // 实现其他空方法 @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { return true; } @Override public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {} }); retryTemplate.setRetryPolicy(retryPolicy); interceptor.setRetryOperations(retryTemplate); return interceptor; } }
3. 轻量手动封装工具类
如果不想引入Spring Retry依赖,也可以封装通用工具类,比你最初的思路更通用:
@Component public class RetryHelper { /** * 执行目标方法,失败后执行补偿方法再重试一次 * @param action 目标方法(方法A) * @param compensation 补偿方法(方法B) * @throws Exception 两次执行都失败时抛出异常 */ public void executeWithRetry(Runnable action, Runnable compensation) throws Exception { try { action.run(); } catch (Exception e) { compensation.run(); // 重试一次 action.run(); } } } // 使用示例 @Service public class BusinessService { @Autowired private RetryHelper retryHelper; public void process() throws Exception { retryHelper.executeWithRetry(this::methodA, this::methodB); } private void methodA() { // 业务逻辑 } private void methodB() { // 补偿逻辑 } }
内容的提问来源于stack exchange,提问作者hetom
相关产品推荐
相关产品推荐

