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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:11:02