如何在多个配置文件不活动时有条件地声明Bean?

Mik*_*din 25 spring spring-boot

在我的Spring-Boot-App中,我想有条件地声明一个Bean,这取决于(un)加载的spring-profiles.

条件:

Profile "a" NOT loaded  
AND  
Profile "b" NOT loaded 
Run Code Online (Sandbox Code Playgroud)

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

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

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

f-C*_*-CJ 37

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

Spring 5.1(Spring Boot 2.1)及以上版本中,它很简单:

@Component
@Profile("!a & !b")
public class MyComponent {}
Run Code Online (Sandbox Code Playgroud)

Spring 4.x和5.0.x中:

这个Spring版本有很多种方法,每种方法都有它的专业版和内容版.当我没有多少组合可以覆盖时,我个人喜欢@Stanislav的答案@Conditional注释.

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

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

Spring:如何在Profiles中做AND?


Sta*_*lav 23

如果您有一个配置文件,则只需使用@Profilenot运算符的注释即可.它还接受多个配置文件,但具有OR条件.

因此,替代解决方案是使用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");
  }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它来注释您的方法,例如:

@Bean
@Conditional(SomeCustomCondition.class)
public MyBean myBean(){/*...*/}
Run Code Online (Sandbox Code Playgroud)


小智 17

我更喜欢这个解决方案,这个解决方案更详细,但仅适用于两个配置文件:

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

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

}
Run Code Online (Sandbox Code Playgroud)


dmy*_*tro 6

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

@Configuration
public class MyBeanConfiguration {

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

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

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

}
Run Code Online (Sandbox Code Playgroud)

  • 像这样使用`@ ConditionalOnMissingBean`很危险.为安全起见,它只应用于自动配置类 (5认同)