迁移至Spring Core重试模块,是否有Sleeper Bean等效实现?
Spring Core重试模块替换无休眠Sleeper的实现方案
Spring Core重试模块没有提供开箱即用的无休眠Sleeper实现,但可以通过自定义退避策略来覆盖默认的Thread.sleep行为,既加快测试速度,又能统计预期的休眠耗时。
- 核心思路:默认的
FixedBackOffPolicy等退避策略内部会调用Thread.sleep,我们可以自定义BackOffPolicy实现,在backOff方法中跳过休眠逻辑,同时记录原本应该休眠的时长。
具体实现步骤
1. 自定义无休眠退避策略
实现BackOffPolicy接口,跳过休眠并统计预期耗时:
import org.springframework.retry.backoff.BackOffContext; import org.springframework.retry.backoff.BackOffPolicy; import java.util.concurrent.atomic.AtomicLong; public class NoSleepBackOffPolicy implements BackOffPolicy { private final AtomicLong totalIntendedSleepTime = new AtomicLong(0); private long fixedSleepDuration = 1000; // 模拟固定退避时长 @Override public BackOffContext start(RetryContext context) { return new NoSleepBackOffContext(); } @Override public void backOff(BackOffContext backOffContext) { // 不执行Thread.sleep,直接累加预期休眠时长 totalIntendedSleepTime.addAndGet(fixedSleepDuration); } // 提供获取总预期耗时的方法,用于断言 public long getTotalIntendedSleepTime() { return totalIntendedSleepTime.get(); } // 可选:支持动态设置退避时长 public void setFixedSleepDuration(long fixedSleepDuration) { this.fixedSleepDuration = fixedSleepDuration; } private static class NoSleepBackOffContext implements BackOffContext {} }
2. 测试中配置RetryTemplate
在集成测试里,给RetryTemplate注入自定义的退避策略:
import org.junit.jupiter.api.Test; import org.springframework.retry.RetryCallback; import org.springframework.retry.policy.SimpleRetryPolicy; import org.springframework.retry.support.RetryTemplate; import static org.junit.jupiter.api.Assertions.assertEquals; public class RetryTest { @Test void testRetryWithoutSleep() { NoSleepBackOffPolicy noSleepBackOffPolicy = new NoSleepBackOffPolicy(); noSleepBackOffPolicy.setFixedSleepDuration(1000); RetryTemplate retryTemplate = new RetryTemplate(); // 设置重试次数 SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(3); // 会触发2次退避 retryTemplate.setRetryPolicy(retryPolicy); // 替换为自定义无休眠退避策略 retryTemplate.setBackOffPolicy(noSleepBackOffPolicy); // 执行带重试的业务逻辑 try { retryTemplate.execute((RetryCallback<Void, RuntimeException>) context -> { throw new RuntimeException("模拟重试触发场景"); }); } catch (RuntimeException ignored) { // 忽略重试最终抛出的异常,专注断言耗时 } // 断言总预期休眠时长:2次退避 × 1000ms = 2000ms assertEquals(2000, noSleepBackOffPolicy.getTotalIntendedSleepTime()); } }
3. 适配指数退避场景
如果你的业务用了指数退避,也可以继承ExponentialBackOffPolicy重写backOff方法:
import org.springframework.retry.backoff.ExponentialBackOffContext; import org.springframework.retry.backoff.ExponentialBackOffPolicy; import java.util.concurrent.atomic.AtomicLong; public class NoSleepExponentialBackOffPolicy extends ExponentialBackOffPolicy { private final AtomicLong totalIntendedSleepTime = new AtomicLong(0); @Override public void backOff(BackOffContext backOffContext) { ExponentialBackOffContext context = (ExponentialBackOffContext) backOffContext; long intendedSleepTime = getSleepAndIncrement(context); totalIntendedSleepTime.addAndGet(intendedSleepTime); // 跳过父类的Thread.sleep逻辑 } public long getTotalIntendedSleepTime() { return totalIntendedSleepTime.get(); } }
内容的提问来源于stack exchange,提问作者whistling_marmot
相关产品推荐
相关产品推荐

