Spring引导ConditionalOnBean注释

时间:2018-05-24 21:51:28

标签: java spring spring-boot

有spring boot 2.0.2配置

@Configuration
public class ApiConfig {

    @Bean
    @Profile("!tests")
    @ConditionalOnProperty(name = "enabled", havingValue = "true")
    public MyService service() {
        return new MyServiceImpl();
    }

}

...以及一些控制器,只有在初始化MyService bean时才应创建并添加到应用程序上下文中。

@RestController
@ConditionalOnBean(MyService.class)
public class MyController {
   @Autowired
   private MyService service;
}

它运作正常。但偶尔弹簧启动会跳过MyController创建。根据日志MyService的创建,但在任何其他bean(包括所有控制器)之后,最后。

为什么启动不会在@Configuration之前处理@RestController个bean? 感谢。

1 个答案:

答案 0 :(得分:2)

  

为什么启动不会在@Controller之前处理@Configuration bean?   感谢。

因为Spring并不能保证这一点 以及@ConditionalOnBean@RestController警告@RestController

  

条件只能匹配已经存在的bean定义   到目前为止,由应用程序上下文处理,因此是   强烈建议在自动配置中使用此条件   仅限类。如果候选bean可能由另一个创建   自动配置,确保使用此条件的那个运行   后。

并且您不会在自动配置类中使用注释。您确实在使用@Configuration注释的类中指定了它。

我认为要实现您的要求,您应该在@ConditionalOnBean类中移动@DependsOn bean声明,或者同时使用this specification@RestController @ConditionalOnBean(MyService.class) @DependsOn("service") public class MyController { @Autowired private MyService service; } 来设置bean实例化:控制器之前的服务。

UPDATE animals_table SET animalname = 'Mary' animaltype = 'Husky' WHERE animalid = '123456' 确实指定为:

  

当前bean所依赖的Bean。指定的任何bean都是   保证在此bean之前由容器创建。

未经测试但您可以尝试类似的第二种解决方案:

UPDATE animals_table
 SET
   animalname = 'Mary'
   animaltype = 'Husky'
 WHERE
   animalid = '123456'
 AND CASE
 WHEN
   dategiven = '1900-01-01'
 THEN
   dategiven = NULL;