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

时间:2016-02-16 09:55:10

标签: spring spring-boot

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

条件:

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

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

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

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

5 个答案:

答案 0 :(得分:20)

如果您只有一个配置文件,则可以使用not运算符使用@Profile注释。它还接受多个配置文件,但具有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");
  }
}

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

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

答案 1 :(得分:17)

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

Spring 5.1(Spring Boot 2.1)及更高版本中很容易:

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

Spring 4.x和5.0.x 中:

此Spring版本有很多方法,每种方法都有其优点和缺点。当没有太多组合需要覆盖时,我个人喜欢带有@Conditional批注的@Stanislav answer

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

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

Spring: How to do AND in Profiles?

答案 2 :(得分:16)

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

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

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

}

答案 3 :(得分:5)

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

@Configuration
public class MyBeanConfiguration {

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

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

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

}

答案 4 :(得分:0)

@Stanislav answer的一种变体,对于5.0.x版或Spring Boot 2.0.x以上的Spring版本,可读性更高。

data.frame

有关Spring / Spring Boot的较新版本,请参见f-CJ answer