Spring Core 7结合Spring Rabbit 4.0.x、Spring Retry 2.0.12实现多异常对应不同重试策略的方案咨询
Spring Core 7结合Spring Rabbit 4.0.x、Spring Retry 2.0.12实现多异常对应不同重试策略的方案咨询
你遇到的这个问题其实是Spring 7版本带来的API迁移变化导致的——Spring 7把原本属于spring-retry模块的核心重试接口(RetryPolicy)迁移到了spring-core包下,而Spring Rabbit 4.0.x已经同步适配了这个新的core包接口,这就导致了之前依赖spring-retry接口的代码和现在的需求出现了冲突。
直接适配Spring Core 7原生重试API的解决方案
最简单的方式是切换到Spring Core 7自带的重试策略实现,它们都在org.springframework.core.retry包下,和Spring Rabbit 4.0.x的要求完全匹配,代码结构和你之前的写法几乎一致,只是需要调整导入的包路径:
import org.springframework.core.retry.RetryPolicy; import org.springframework.core.retry.policy.SimpleRetryPolicy; import org.springframework.core.retry.policy.AlwaysRetryPolicy; import org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy; import java.sql.SQLException; import java.net.SocketException; import java.util.Map; // 构建针对不同异常的重试策略 final RetryPolicy sqlRetryPolicy = new SimpleRetryPolicy(3); final RetryPolicy connectionRetryPolicy = new AlwaysRetryPolicy(); // 创建分类重试策略并绑定异常与策略的对应关系 ExceptionClassifierRetryPolicy classifierRetryPolicy = new ExceptionClassifierRetryPolicy(); classifierRetryPolicy.setPolicyMap(Map.of( SQLException.class, sqlRetryPolicy, SocketException.class, connectionRetryPolicy )); return classifierRetryPolicy;
兼容原有spring-retry策略的适配方案
如果你有遗留的自定义spring-retry策略不想重写,可以通过一个适配器类,把spring-retry的RetryPolicy转换为spring-core的RetryPolicy:
首先编写适配器:
import org.springframework.retry.RetryPolicy; import org.springframework.core.retry.RetryPolicy; import org.springframework.core.retry.RetryContext; // 用别名区分两个同名接口(如果你的开发环境支持),或者直接用全限定类名转换 public class SpringRetryToCoreAdapter implements org.springframework.core.retry.RetryPolicy { private final org.springframework.retry.RetryPolicy delegate; public SpringRetryToCoreAdapter(org.springframework.retry.RetryPolicy delegate) { this.delegate = delegate; } @Override public boolean canRetry(RetryContext context) { // 注意上下文类型的转换 return delegate.canRetry((org.springframework.retry.RetryContext) context); } @Override public RetryContext open(RetryContext parent) { return delegate.open((org.springframework.retry.RetryContext) parent); } @Override public void close(RetryContext context) { delegate.close((org.springframework.retry.RetryContext) context); } @Override public void registerThrowable(RetryContext context, Throwable throwable) { delegate.registerThrowable((org.springframework.retry.RetryContext) context, throwable); } }
然后用适配器包装原有策略:
// 原有spring-retry的策略实现 final org.springframework.retry.policy.SimpleRetryPolicy retryWithMaxAttempts = new org.springframework.retry.policy.SimpleRetryPolicy(3); final org.springframework.retry.policy.AlwaysRetryPolicy connectionRetryPolicy = new org.springframework.retry.policy.AlwaysRetryPolicy(); // 转换为spring-core兼容的策略 org.springframework.core.retry.RetryPolicy sqlRetryPolicy = new SpringRetryToCoreAdapter(retryWithMaxAttempts); org.springframework.core.retry.RetryPolicy connRetryPolicy = new SpringRetryToCoreAdapter(connectionRetryPolicy); // 用core的分类策略组装 org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy classifierRetryPolicy = new org.springframework.core.retry.policy.ExceptionClassifierRetryPolicy(); classifierRetryPolicy.setPolicyMap(Map.of( SQLException.class, sqlRetryPolicy, SocketException.class, connRetryPolicy )); return classifierRetryPolicy;
问题根源总结
Spring 7对重试模块做了架构调整,将核心API整合到spring-core中,目的是减少模块依赖、统一重试逻辑的标准。Spring Rabbit 4.0.x作为适配Spring 7的版本,自然切换到了新的core接口,这就导致了旧代码中spring-retry接口和新接口的冲突。只要切换到新的包路径或者通过适配器兼容,就能解决这个问题。
备注:内容来源于stack exchange,提问作者nagaraj gond




