我有一个实现Runnable的原型bean,必须重试其run-method并在达到最大重试次数时执行某些操作。 现在我遇到的问题是,似乎总是从相同的Spring bean调用recover方法,而不是从相应的实例调用。
到目前为止,这是我的代码:
RetryableRunnable
@Slf4j
@AllArgsConstructor
public class RetryableRunnable implements Runnable {
private final RetryDemoService retryDemoService;
private final Status someStatus;
@Override
@Retryable(
value = { RuntimeException.class },
maxAttempts = 2,
backoff = @Backoff(delay = 2000))
public void run() {
log.info( "+++ RetryableRunnable executed! +++" );
retryDemoService.demoRun();
}
@Recover
private void recover() {
retryDemoService.demoRecover();
log.info( String.valueOf( someStatus ) );
}
}
配置
@Configuration
@AllArgsConstructor
@EnableRetry(proxyTargetClass = true)
public class RetryDemoConfig {
private final RetryDemoService retryDemoService;
@Bean
@Scope( "prototype" )
public RetryableRunnable retryableRunnable(Status status) {
return new RetryableRunnable( retryDemoService, status );
}
}
服务
@Service
@Slf4j
public class RetryDemoService {
void demoRun() {
log.info( "+++ Run! +++" );
}
void demoRecover() {
log.info( "+++ Recover! +++" );
}
}
状态枚举
public enum Status {
STATUS1, STATUS2
}
测试以显示问题
@RunWith( SpringRunner.class )
@SpringBootTest
public class RetryableRunnableTest {
@Autowired
private BeanFactory beanFactory;
@MockBean
RetryDemoService retryDemoService;
@Test
public void retrieableRunnableIsRetriedOnlyThreeTimesAndRecoverMethodIsRun() throws InterruptedException {
RetryableRunnable testInstance1 = beanFactory.getBean( RetryableRunnable.class, Status.STATUS1 );
RetryableRunnable testInstance2 = beanFactory.getBean( RetryableRunnable.class, Status.STATUS2 );
doThrow( new RuntimeException() )
.doThrow( new RuntimeException() )
.doThrow( new RuntimeException() )
.when( retryDemoService ).demoRun();
Thread thread1 = new Thread( testInstance1 );
thread1.start();
thread1.join();
Thread thread2 = new Thread( testInstance2 );
thread2.start();
thread2.join();
}
}
现在日志的输出是:
+++ RetryableRunnable executed! +++
+++ RetryableRunnable executed! +++
STATUS1
+++ RetryableRunnable executed! +++
+++ RetryableRunnable executed! +++
STATUS1
虽然它应该是:
+++ RetryableRunnable executed! +++
+++ RetryableRunnable executed! +++
STATUS1
+++ RetryableRunnable executed! +++
+++ RetryableRunnable executed! +++
STATUS2
当我调试这个测试方法时,第一次和第二次由RetryRunnable @ 3053调用recover方法!
这是一个错误还是我错过了对概念的理解?我该怎么做才能解决这个问题并调用相应的原型bean" Status" -field?