Spring Retry排除规则失效:MessageTimeoutException未按预期不重试
以下是几个可能导致配置失效的原因及对应的解决方向:
1. 自定义retryAdvice未处理exclude属性
你之前自定义的retryAdvice()可能完全接管了重试逻辑,没有读取@Retryable注解中的exclude配置项。比如原来的Advice逻辑仅判断异常是否属于value指定的Exception.class,完全忽略了exclude规则。
解决方式:
在自定义Advice中,需要通过注解解析器获取@Retryable的exclude属性,在判断是否触发重试时排除这些异常类型。示例代码片段:
// 获取@Retryable注解的exclude属性 Retryable retryable = method.getAnnotation(Retryable.class); Class<? extends Throwable>[] excludeExceptions = retryable.exclude(); // 判断当前异常是否属于排除列表 for (Class<? extends Throwable> exclude : excludeExceptions) { if (exclude.isInstance(throwable)) { return false; // 不重试 } } // 再判断是否属于需要重试的异常类型 return retryable.value()[0].isInstance(throwable);
2. MessageTimeoutException被其他异常包裹
如果日志中抛出的不是直接的MessageTimeoutException,而是被外层异常(比如RuntimeException、自定义业务异常)包裹的,那么@Retryable的exclude配置不会生效——因为Spring Retry只会识别抛出的最上层异常,不会自动解析异常链中的cause。
解决方式:
- 查看完整异常栈轨迹,确认实际抛出的异常类型;
- 如果是包裹异常,可以将外层异常加入
exclude列表,或者在重试逻辑中递归检查异常的getCause(),判断是否包含MessageTimeoutException。
3. 重试拦截器配置冲突
如果自定义的retryAdvice没有正确集成Spring Retry的默认规则,而是完全自定义了重试触发逻辑,那么@Retryable注解的exclude等属性自然不会被应用。
解决方式:
尽量基于Spring Retry的RetryTemplate和AnnotationAwareRetryOperationsInterceptor来构建自定义Advice,而非完全从零实现,这样可以自动继承注解中的所有配置项。
4. @EnableRetry未正确配置
如果你的配置类上没有添加@EnableRetry注解,或者注解的proxyTargetClass等属性配置错误,可能导致@Retryable注解的属性无法被正确解析。
解决方式:
确认配置类上存在@EnableRetry,并根据你的代理方式(JDK动态代理/CGLIB)配置正确的proxyTargetClass属性。
内容的提问来源于stack exchange,提问作者lavin249

