【问题标题】:What does the spring annotation @ConditionalOnMissingBean do?spring注解@ConditionalOnMissingBean有什么作用?
【发布时间】:2018-06-11 11:36:19
【问题描述】:

我正在尝试启动已使用此注释的 springboot 应用程序。当我尝试启动应用程序时,它给了我以下错误:

org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException 无法推断 com.shutterfly.sbs.platform.SbsPlatformConfigurationClientConfig.getRestTemplate 的 bean 类型

代码:

@ConditionalOnMissingBean
@Bean
public RestTemplate getRestTemplate() {
    return new RestTemplate();
}

【问题讨论】:

  • 只有当在上下文中找不到 RestTemplate bean 时才会初始化 bean。如果它已经有一个 RestTemplate bean,它将跳过这个。
  • 谢谢@pvpkiran

标签: java spring spring-boot


【解决方案1】:

@ConditionalOnMissingBean 注释仅用于在缺少给定 bean 时加载 bean:

@Bean
@ConditionalOnMissingBean(SomeBean.class)
public SomeBean otherBean(){
    return new SomeBean();
}

只有当上下文中没有其他这种类型的 bean 时,上面的 bean 才会被 Spring 加载。另一方面,如果应用上下文中已经存在 SomeBean 类型的 bean,则不会创建上述 bean。

此注释派上用场的一些用例是:

  • 指定一个备用 bean,如果不存在相同类型的 bean,则该 bean 仅作为备份加载(例如:如果没有配置真正的数据库,则使用内存数据库)
  • 指定一个默认 bean,在上下文中存在相同类型的更具体 bean 的情况下允许被覆盖(例如:使用默认身份验证机制,除非有人决定用他自己的自定义身份验证替换它)

参考:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

【讨论】:

  • 注意添加 bean 定义的顺序,因为这些条件是根据目前已处理的内容评估的(来自 spring 文档)
  • 答案很好,但是@Mike Rylander 提到的关于 applicationContext 中的 bean 的声明在这里丢失了。
【解决方案2】:

@ConditionalOnMissingBean 注解是一个 spring 条件注解,仅当 bean 尚未在应用程序上下文中时才注册它们。

查看文档:https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.html

【讨论】:

    【解决方案3】:

    如果我们只想在指定的 bean 不存在时包含一个 bean,我们使用@ConditionalOnMissingBean。例如。

    让我们配置一个 transactionManager bean,它仅在 JpaTransactionManager 类型的 bean 尚未定义时才被加载:

    @Bean
    @ConditionalOnMissingBean(type = "JpaTransactionManager")
    JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
    

    要了解更多信息,请考虑这种情况

    假设在我的项目中我配置了一个 bean videoDecoderService

    @Bean
    @ConditionalOnMissingBean(VideoDecoderService.class)
    public videoDecoderService videoDecoderService(){
    return new VideoDecoderService;
    }
    

    它将做的是,任何使用我的项目的人都可以用他们自己的videoDecoderService 覆盖videoDecoderService。如果他们没有编写自己的videoDecoderService,则将提供此默认值。

    【讨论】:

      【解决方案4】:

      您不应跳过文档中明确说明的部分:

      该条件只能匹配到目前为止已由应用程序上下文处理的 bean 定义,因此,强烈建议仅在自动配置类上使用此条件。

      后面接着说:

      如果候选 bean 可能由另一个自动配置创建,请确保使用此条件的 bean 在之后运行

      简单来说,这可能意味着某些other 自动配置引入的@Bean 应该优先于您定义的那个。为此,您需要通过@AutoConfigureBefore 正确设置这些配置的顺序。

      【讨论】:

        猜你喜欢
        • 2019-02-16
        • 2015-07-31
        • 1970-01-01
        • 2013-10-18
        • 2019-01-08
        • 2020-03-06
        • 2015-01-15
        • 1970-01-01
        • 2020-03-19
        相关资源
        最近更新 更多