春季:如何在配置文件中执行 AND?

2022-08-31 22:25:44

弹簧轮廓注释允许您选择轮廓。但是,如果您阅读文档,它只允许您使用 OR 操作选择多个配置文件。如果指定@Profile(“A”、“B”),则当配置文件 A 或配置文件 B 处于活动状态时,您的 Bean 将启动。

我们的用例是不同的,我们希望支持多个配置的 TEST 和 PROD 版本。因此,有时我们希望仅在配置文件 TEST 和 CONFIG1 都处于活动状态时才自动连接 Bean。

有没有办法用春天做到这一点?最简单的方法是什么?


答案 1

从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:只需使用和创建所需组合的任意数量的实现。它的缺点是必须创建与组合一样多的实现,但是如果您没有很多组合,在我看来,它是一个更简洁的解决方案,它提供了更大的灵活性和实现更复杂的逻辑解决方案的机会。@ConditionalCondition

方法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)

只是想为您的问题提供更新的答案并补充其他答案。


答案 2

由于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

注意:我没有检查所有角情况(如空,长度检查等)。但是,这个方向可能会有所帮助。


推荐