春季:如何在配置文件中执行 AND?
弹簧轮廓注释允许您选择轮廓。但是,如果您阅读文档,它只允许您使用 OR 操作选择多个配置文件。如果指定@Profile(“A”、“B”),则当配置文件 A 或配置文件 B 处于活动状态时,您的 Bean 将启动。
我们的用例是不同的,我们希望支持多个配置的 TEST 和 PROD 版本。因此,有时我们希望仅在配置文件 TEST 和 CONFIG1 都处于活动状态时才自动连接 Bean。
有没有办法用春天做到这一点?最简单的方法是什么?
弹簧轮廓注释允许您选择轮廓。但是,如果您阅读文档,它只允许您使用 OR 操作选择多个配置文件。如果指定@Profile(“A”、“B”),则当配置文件 A 或配置文件 B 处于活动状态时,您的 Bean 将启动。
我们的用例是不同的,我们希望支持多个配置的 TEST 和 PROD 版本。因此,有时我们希望仅在配置文件 TEST 和 CONFIG1 都处于活动状态时才自动连接 Bean。
有没有办法用春天做到这一点?最简单的方法是什么?
从Spring 5.1(合并到Spring Boot 2.1中)开始,可以在配置文件字符串注释中使用配置文件表达式。所以:
在Spring 5.1(Spring Boot 2.1)及更高版本中,它就像:
@Component
@Profile("TEST & CONFIG1")
public class MyComponent {}
弹簧 4.x 和 5.0.x:
方法1:由@Mithun回答,它完美地涵盖了您在配置文件注释中将OR转换为AND的情况,每当您也使用他的类实现注释Spring Bean时。但我想提供另一种没有人提出的方法,这种方法有其优点和缺点。Condition
方法2:只需使用和创建所需组合的任意数量的实现。它的缺点是必须创建与组合一样多的实现,但是如果您没有很多组合,在我看来,它是一个更简洁的解决方案,它提供了更大的灵活性和实现更复杂的逻辑解决方案的机会。@Conditional
Condition
方法2的实施情况如下。
你的春豆:
@Component
@Conditional(value = { TestAndConfig1Profiles.class })
public class MyComponent {}
TestAndConfig1Profiles
实现:
public class TestAndConfig1Profiles implements Condition {
@Override
public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
return context.getEnvironment().acceptsProfiles("TEST")
&& context.getEnvironment().acceptsProfiles("CONFIG1");
}
}
使用这种方法,您可以轻松地涵盖更复杂的逻辑情况,例如:
(TEST & CONFIG1) |(TEST & CONFIG3)
只是想为您的问题提供更新的答案并补充其他答案。
由于Spring不提供开箱即用的AND功能。我会建议以下策略:
当前注释具有条件注释 。在其中循环访问配置文件并检查配置文件是否处于活动状态。同样,您可以创建自己的条件实现并限制注册 Bean。例如:@Profile
@Conditional(ProfileCondition.class)
ProfileCondition.class
public class MyProfileCondition implements Condition {
@Override
public boolean matches(final ConditionContext context,
final AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
final MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (final Object value : attrs.get("value")) {
final String activeProfiles = context.getEnvironment().getProperty("spring.profiles.active");
for (final String profile : (String[]) value) {
if (!activeProfiles.contains(profile)) {
return false;
}
}
}
return true;
}
}
return true;
}
}
在你的课堂上:
@Component
@Profile("dev")
@Conditional(value = { MyProfileCondition.class })
public class DevDatasourceConfig
注意:我没有检查所有角情况(如空,长度检查等)。但是,这个方向可能会有所帮助。