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

MicroProfile Fault Tolerance Retry注解内外调用行为确认

问题确认:MicroProfile Fault Tolerance内部调用不触发Retry规则?

你的判断完全正确——当@Retry注解的方法被Bean外部直接调用时,重试规则生效;当该方法被Bean内部其他方法调用时,重试规则不会生效。

原因分析

MicroProfile Fault Tolerance的注解是基于CDI拦截器实现的,而CDI拦截器仅会拦截对Bean代理对象的外部调用:

  • 当从Bean外部调用注解方法时,实际调用的是CDI容器生成的代理对象,拦截器会介入并触发注解对应的容错策略;
  • 当在Bean内部调用自身的注解方法时,调用的是原始对象的方法,没有经过代理层,因此注解的规则不会被触发。

结合代码示例验证

你的Bean定义:

import org.eclipse.microprofile.faulttolerance.Retry;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.SneakyThrows;

@ApplicationScoped
public class MyService {

    private int retryCount = 0;

    @SneakyThrows
    private void throwConnectException() {
        throw new ConnectException("Test");
    }

    public void call_testRetryMethod() {
        testRetryMethod();
    }

    @Retry(maxRetries = 5)
    public void testRetryMethod() {
        LOGGER.info("testRetryMethod: {}", retryCount++);
        throwConnectException();
    }

}

单元测试代码:

import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
class MyServiceTest {
    @Inject MyService myService;

    @Test
    public void testMyService() {
        myService.testRetryMethod(); // 此调用会重试6次(初始调用+5次重试)
        myService.call_testRetryMethod(); // 此调用不会重试,仅执行1次
    }
}
  • myService.testRetryMethod():外部直接调用代理对象的方法,拦截器生效,触发@Retry规则,执行6次;
  • myService.call_testRetryMethod():外部调用代理对象的call_testRetryMethod方法后,内部直接调用原始对象的testRetryMethod,未经过代理,因此@Retry不生效。

对应文档说明

MicroProfile Fault Tolerance 4.0文档中的描述翻译为:

当调用带有注解的方法时,该调用会被拦截,对应的容错策略会应用到方法的执行过程中。

这里的“调用带有注解的方法”特指通过代理对象的外部调用,内部直接调用不在拦截范围内,这是CDI拦截器的通用特性,其他依赖拦截器实现的注解(如@Transactional)也遵循同样的规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:57:18