Spring重试@Recover方法实现了原型bean实现Runnable而不使用原型bean

时间:2017-11-27 14:58:56

标签: spring spring-boot spring-retry

我有一个实现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?

0 个答案:

没有答案