Spring:如何使服务以 PlatformTransactionManager bean 的可用性为条件?

Spring: How to make a service conditional on the availability of a PlatformTransactionManager bean?

我有一个 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 bean 可用,因为当我 @Autowire 在我的测试中使用 PlatformTransactionManager 而不是 FooService.

有趣的是,我还尝试用 WebClient.Builder 替换 PlatformTransactionManager,最后一切正常。 PlatformTransactionManager有什么特别之处?

如何编写 FooService 以便它在 PlatformTransactionManager bean 可用时工作,并且不阻止没有此类 bean 可用的应用程序启动?

添加 @AutoConfigureOrder 注释以确保在 Spring Boot:

注册事务管理器 bean 之后处理您的自动配置 class
@Configuration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public class FooAutoConfiguration {

}