@Retryable注解value属性未按预期生效 配置指定异常仍触发所有异常重试
@Retryable注解异常过滤失效问题原因及解决方案
问题原因
- Spring Retry版本缺陷:1.2.5之前的Spring Retry版本存在已知BUG,当被
@Retryable标注的方法同时配有@Recover恢复方法时,注解value属性的异常过滤逻辑会失效,所有RuntimeException都会触发重试。 - 全局配置覆盖:如果容器中存在自定义的全局
RetryTemplateBean,且该Bean的重试策略配置为对所有异常重试,@Retryable注解默认会复用该全局配置,覆盖注解上的value属性配置。 - 异常包装场景:如果业务代码中存在其他AOP切面或者异常捕获逻辑,将原本的非指定异常包装为
IllegalArgumentException抛出,也会触发重试,可通过打印完整异常栈排查该情况。
解决方案
- 优先升级Spring Retry版本到1.2.5及以上,该版本官方已经修复了
@Recover导致的异常过滤失效BUG。 - 版本无法升级时,显式在
@Retryable注解中添加exclude属性,明确排除不需要重试的异常,配置示例:
@Retryable(value = {IllegalArgumentException.class}, exclude = {HttpClientErrorException.class, Exception.class}, maxAttempts = 2, backoff = @Backoff(delay = 50))
- 存在全局
RetryTemplate配置的场景,可在@Retryable注解中通过exceptionExpression属性显式指定异常匹配规则,强制只对指定异常重试,配置示例:
@Retryable(value = {IllegalArgumentException.class}, exceptionExpression = "T(java.lang.IllegalArgumentException).isInstance(#root)", maxAttempts = 2, backoff = @Backoff(delay = 50))
- 针对查找
@Recover方法耗时的问题,可添加兜底恢复方法,避免异常匹配时的遍历消耗:
@Recover public ResponseEntity<Object> recoverAll(Exception e, UUID subscriptionId){ // 可根据需求选择直接抛出原异常或者返回通用降级结果 throw e; }
内容的提问来源于stack exchange,提问作者Ignacio Escursell
相关产品推荐
相关产品推荐

