spring 当多个配置文件未处于活动状态时如何有条件地声明 Bean?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35429168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:59:08  来源:igfitidea点击:

How to conditionally declare Bean when multiple profiles are not active?

springspring-boot

提问by Mike Boddin

In my Spring-Boot-App I want to conditionally declare a Bean, depending on (un)loaded spring-profiles.

在我的 Spring-Boot-App 中,我想根据(未)加载的 spring-profiles 有条件地声明一个 Bean。

The conditon:

条件:

Profile "a" NOT loaded  
AND  
Profile "b" NOT loaded 

My solution so far (which works):

到目前为止我的解决方案(有效):

@Bean
@ConditionalOnExpression("#{!environment.getProperty('spring.profiles.active').contains('a') && !environment.getProperty('spring.profiles.active').contains('b')}")
    public MyBean myBean(){/*...*/}

Is there a more elegant (and shorter) way to explain this condition?
Especially I want to get rid of the usage of Spring Expression Language here.

有没有更优雅(和更短)的方式来解释这种情况?
特别是我想在这里摆脱 Spring Expression Language 的使用。

回答by f-CJ

Since Spring 5.1.4 (incorporated in Spring Boot 2.1.2) it is possible to use a profile expression inside profile string annotation. So:

从 Spring 5.1.4(包含在 Spring Boot 2.1.2 中)开始,可以在配置文件字符串注释中使用配置文件表达式。所以:

In Spring 5.1.4 (Spring Boot 2.1.2) and aboveit is as easy as:

Spring 5.1.4 (Spring Boot 2.1.2) 及更高版本中,它很简单:

@Component
@Profile("!a & !b")
public class MyComponent {}

In Spring 4.x and 5.0.x:

Spring 4.x 和 5.0.x 中

There are many approaches for this Spring versions, each one of them has its pro's and con's. When there aren't many combinations to cover I personally like @Stanislav answerwith the @Conditionalannotation.

这个 Spring 版本有很多方法,每一种都有其优点和缺点。当没有太多组合可以覆盖时,我个人喜欢@Stanislav带有@Conditional注释的回答

Other approaches can be found in this similar questions:

其他方法可以在这个类似的问题中找到:

Spring Profile - How to include AND condition for adding 2 profiles?

Spring Profile - 如何包含 AND 条件以添加 2 个配置文件?

Spring: How to do AND in Profiles?

Spring:如何在 Profiles 中做 AND?

回答by Stanislav

If you have a single profile you could simply use a @Profileannotation with the not operator. It also accepts multiple profiles, but with the ORcondition.

如果您只有一个配置文件,您可以简单地使用@Profile带有 not 运算符的注释。它还接受多个配置文件,但OR有条件。

So, the alternative solution is to use a custom Conditionwith the @Conditionalannotation. Like so:

因此,替代解决方案是使用Condition带有@Conditional注释的自定义。像这样:

public class SomeCustomCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

    // Return true if NOT "a" AND NOT "b"
    return !context.getEnvironment().acceptsProfiles("a") 
                  && !context.getEnvironment().acceptsProfiles("b");
  }
}

And then annotate your method with it, like:

然后用它注释你的方法,比如:

@Bean
@Conditional(SomeCustomCondition.class)
public MyBean myBean(){/*...*/}

回答by willerr

I prefer this solution which is more verbose but still fine for two profiles only:

我更喜欢这个更冗长但仅适用于两个配置文件的解决方案:

@Profile("!a")
@Configuration
public class NoAConfig {

    @Profile("!b")
    @Configuration
    public static class NoBConfig {
        @Bean
        public MyBean myBean(){
            return new MyBean();
        }
    }

}

回答by dmytro

Unfortunately I don't have a shorter solution for you, but if it is suitable in your case to create the same beans for each profile, you may consider the following approach.

不幸的是,我没有为您提供更短的解决方案,但如果适合您的情况为每个配置文件创建相同的 bean,您可以考虑以下方法。

@Configuration
public class MyBeanConfiguration {

   @Bean
   @Profile("a")
   public MyBean myBeanForA() {/*...*/}

   @Bean
   @Profile("b")
   public MyBean myBeanForB() {/*...*/}

   @Bean
   @ConditionalOnMissingBean(MyBean.class)
   public MyBean myBeanForOthers() {/*...*/}

}