Spring: Как сделать сервис зависящим от доступности bean-компонента PlatformTransactionManager? - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть FooService, который я хотел бы быть доступным, только когда доступен PlatformTransactionManager.

Если я определю свой сервис таким образом, а PlatformTransactionManager не будет доступен, то мое приложение будетне удалось запустить:

@Service
public class FooService {
  public FooService(final PlatformTransactionManager txManager) { ... }
  ...
}

Я хотел использовать ConditionalOnBean, который должен аннотировать только классы автоматической конфигурации.Я реорганизовал свой код следующим образом:

@Configuration
public class FooAutoConfiguration {
  @Bean
  @ConditionalOnBean(PlatformTransactionManager.class)
  public FooService fooService(final PlatformTransactionManager txManager) {
    return new FooService(txManager);
  }
}

public class FooService {
  public FooService(final BarBean bar) { ... }
  ...
}

Я написал следующий тест для FooService:

@ExtendWith(SpringExtension.class)
@Import(FooAutoConfiguration.class)
public class FooServiceTest {
  @Autowired
  private FooService fooService;

  @Test
  public void test() {
    System.out.println("fooService = " + fooService);
  }
}

Но я получаю следующее исключение при попытке его запустить:


org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.acme.FooServiceTest': Unsatisfied dependency expressed through field 'fooService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.acme.FooService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
(...)

Однако я знаю, что доступен компонент PlatformTransactionManager, потому что тест выполняется нормально, когда в моем тесте я @Autowire a PlatformTransactionManager вместо FooService.

Интересно, что я также попытался заменить PlatformTransactionManager на WebClient.Builder, и все в итоге работает как надо.Что такого особенного в PlatformTransactionManager?

Как я могу написать FooService, чтобы он работал, когда доступен компонент PlatformTransactionManager, и не препятствовал запуску приложений, в которых такой компонент недоступен?

1 Ответ

0 голосов
/ 21 февраля 2019

Добавить @AutoConfigureOrder аннотацию, чтобы гарантировать, что ваш класс автоконфигурации обработан после регистрации bean-компонента менеджера транзакций в Spring Boot:

@Configuration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public class FooAutoConfiguration {

}
...