首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >春天:如何做和在Profiles?

春天:如何做和在Profiles?
EN

Stack Overflow用户
提问于 2014-11-21 06:02:27
回答 7查看 41.4K关注 0票数 50

Spring Profile注释允许您选择概要文件。但是,如果您阅读文档,它只允许您使用OR操作选择多个配置文件。如果您指定@ profile ("A","B"),那么如果配置文件A或配置文件B是活动的,那么bean就会启动。

我们的用例是不同的,我们希望支持多个配置的测试和PROD版本。因此,有时我们只想在配置文件测试和CONFIG1都处于活动状态时才自动使用bean。

有什么办法可以用春天吗?最简单的方法是什么?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2014-11-21 08:17:51

因为Spring没有提供开箱即用的特性。我建议以下策略:

目前,@Profile注释有一个条件注释@Conditional(ProfileCondition.class)。在ProfileCondition.class中,它迭代配置文件并检查概要文件是否是活动的。类似地,您可以创建自己的条件实现,并限制注册bean。例如:

代码语言:javascript
复制
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;
    }

}

在你们班:

代码语言:javascript
复制
@Component
@Profile("dev")
@Conditional(value = { MyProfileCondition.class })
public class DevDatasourceConfig

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

票数 26
EN

Stack Overflow用户

发布于 2018-10-17 13:43:54

自从Spring5.1(包含在Spring 2.1中)之后,就可以在概要文件字符串注释中使用配置文件表达式。所以:

Spring5.1(SpringBoot2.1)及其以上的中,它非常容易实现:

代码语言:javascript
复制
@Component
@Profile("TEST & CONFIG1")
public class MyComponent {}

Spring4.x和5.0.x

  • 方法1:answered by @Mithun,它完美地涵盖了每当您用Spring的Condition类实现注释Spring时将OR转换为或在概要注释中的情况。但我想提供另一种没有人提议的方法,那就是有正反两方面的。
  • 方法2:只需使用@Conditional并根据需要创建尽可能多的Condition实现。它的缺点是必须创建与组合一样多的实现,但是如果您没有很多组合,我认为它是一个更简洁的解决方案,它提供了更多的灵活性和实现更复杂的逻辑解决方案的机会。

办法2的实施情况如下。

你的春豆:

代码语言:javascript
复制
@Component
@Conditional(value = { TestAndConfig1Profiles.class })
public class MyComponent {}

TestAndConfig1Profiles实现:

代码语言:javascript
复制
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) x (TEST & CONFIG3)

只是想对你的问题给出一个最新的答案,并补充其他答案。

票数 39
EN

Stack Overflow用户

发布于 2015-09-18 09:12:59

@Mithun回答的一个改进版本:

代码语言:javascript
复制
public class AndProfilesCondition implements Condition {

public static final String VALUE = "value";
public static final String DEFAULT_PROFILE = "default";

@Override
public boolean matches(final ConditionContext context, final AnnotatedTypeMetadata metadata) {
    if (context.getEnvironment() == null) {
        return true;
    }
    MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
    if (attrs == null) {
        return true;
    }
    String[] activeProfiles = context.getEnvironment().getActiveProfiles();
    String[] definedProfiles = (String[]) attrs.getFirst(VALUE);
    Set<String> allowedProfiles = new HashSet<>(1);
    Set<String> restrictedProfiles = new HashSet<>(1);
    for (String nextDefinedProfile : definedProfiles) {
        if (!nextDefinedProfile.isEmpty() && nextDefinedProfile.charAt(0) == '!') {
            restrictedProfiles.add(nextDefinedProfile.substring(1, nextDefinedProfile.length()));
            continue;
        }
        allowedProfiles.add(nextDefinedProfile);
    }
    int activeAllowedCount = 0;
    for (String nextActiveProfile : activeProfiles) {
        // quick exit when default profile is active and allowed profiles is empty
        if (DEFAULT_PROFILE.equals(nextActiveProfile) && allowedProfiles.isEmpty()) {
            continue;
        }
        // quick exit when one of active profiles is restricted
        if (restrictedProfiles.contains(nextActiveProfile)) {
            return false;
        }
        // just go ahead when there is no allowed profiles (just need to check that there is no active restricted profiles)
        if (allowedProfiles.isEmpty()) {
            continue;
        }
        if (allowedProfiles.contains(nextActiveProfile)) {
            activeAllowedCount++;
        }
    }
    return activeAllowedCount == allowedProfiles.size();
}

}

无法在评论中发布。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27055072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档