我可以否定(!)弹簧配置文件的集合吗?

2022-09-01 05:03:47

是否可以以一组概要文件不会使用的方式配置 Bean?目前我可以这样做(我相信):

@Profile("!dev, !qa, !local")

有没有更整洁的符号来实现这一点?让我们假设我有很多配置文件。另外,如果我有一些服务(或其他什么)的模拟和具体实现,我可以只注释其中一个,并假设另一个将在所有其他情况下使用吗?换句话说,例如,这是必要的:

@Profile("dev, prof1, prof2")
public class MockImp implements MyInterface {...}

@Profile("!dev, !prof1, !prof2") //assume for argument sake that there are many other profiles
public class RealImp implements MyInterface {...}

我可以只注释其中一个,然后在另一个上贴上注释吗?@Primary

从本质上讲,我想要这个:

@Profile("!(dev, prof1, prof2)")

提前致谢!


答案 1

从Spring 5.1(合并到Spring Boot 2.1中)开始,可以在配置文件字符串注释中使用配置文件表达式(有关详细信息,请参阅Profile.of(..)中的说明)。

因此,要从某些配置文件中排除您的Bean,您可以使用如下表达式:

@Profile("!dev & !prof1 & !prof2")

也可以使用其他逻辑运算符,例如:

@Profile("test | local")

答案 2

简短的回答是:你不能在Spring 5.1之前的Spring版本中(即2.1之前的Spring Boot版本)。

但是,由于注释,存在一个整洁的解决方法。@Conditional

创建条件匹配器:

public static abstract class ProfileCondition extends SpringBootCondition {
    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        if (matchProfiles(conditionContext.getEnvironment())) {
            return ConditionOutcome.match("A local profile has been found.");
        }
        return ConditionOutcome.noMatch("No local profiles found.");
    }

    protected static abstract boolean matchProfiles(final Environment environment);
}

public class DevProfileCondition extends ProfileCondition {
   protected boolean matchProfiles(final Environment environment) {    
        return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> {
            return prof.equals("dev") || prof.equals("prof1") || prof.equals("prof2");
        });
    }
}

public static class ProdProfileCondition extends ProfileCondition {
   protected boolean matchProfiles(final Environment environment) {    
        return Arrays.stream(environment.getActiveProfiles()).anyMatch(prof -> {
            return (!prof.equals("dev") && !prof.equals("prof1") && !prof.equals("prof2"));
        });
    }
}

使用它

@Conditional(value = {DevProfileCondition.class})
public class MockImpl implements MyInterface {...}

@Conditional(value = {ProdProfileCondition.class})
public class RealImp implements MyInterface {...}

然而,这种阿普鲁奇需要春靴。


推荐