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
相关产品推荐
相关产品推荐

