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
How to conditionally declare Bean when multiple profiles are not active?
提问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 @Conditional
annotation.
这个 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 个配置文件?
回答by Stanislav
If you have a single profile you could simply use a @Profile
annotation with the not operator. It also accepts multiple profiles, but with the OR
condition.
如果您只有一个配置文件,您可以简单地使用@Profile
带有 not 运算符的注释。它还接受多个配置文件,但OR
有条件。
So, the alternative solution is to use a custom Condition
with the @Conditional
annotation. 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() {/*...*/}
}