在我的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表达式语言的使用。
答案 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?
答案 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。