java Spring Boot 配置跳过多个@Profile 上的注册

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35252262/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:54:52  来源:igfitidea点击:

Spring Boot Configuration skip registration on multiple @Profile

javaspringspring-bootspring-profiles

提问by gtiwari333

I've a Spring Boot application with different Profile setup : dev, prod, qc, consoleetc.

我曾与不同的配置文件设置一个春天启动应用程序:devprodqcconsole等。

The two configuration classes are setup as follows. MyConfigurationAshould be registered for all profiles except console. MyConfigurationBshould be registered except for consoleand dev.

这两个配置类设置如下。MyConfigurationA应该为所有配置文件注册,除了console. MyConfigurationB应该注册,除了consoledev

When I run the application with profile console, the MyConfigurationAdoesn't get registered - which is fine. But MyConfigurationBgets registered - which I do not want. I've setup the @Profileannotation as follows to not register the MyConfigurationBfor profile consoleand dev.

当我使用 profile 运行应用程序时consoleMyConfigurationA它没有被注册 - 这很好。但是MyConfigurationB被注册了——这是我不想要的。我已@Profile按如下方式设置注释以不注册MyConfigurationBfor 配置文件 consoledev.

But the MyConfigurationBis getting registered when I run the application with profile console.

但是MyConfigurationB当我使用 profile 运行应用程序时,它正在注册console

@Profile({ "!" + Constants.PROFILE_CONSOLE ,  "!" + Constants.PROFILE_DEVELOPMENT })


The documentation ( http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Profile.html) has an example of including one profile and excluding the other. In my example I'm excluding both as @Profile({"!p1", "!p2"}):

文档(http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Profile.html)有一个包含一个配置文件而排除另一个配置文件的示例。在我的例子中,我将两者都排除在外@Profile({"!p1", "!p2"}):

@Profile({"p1", "!p2"}), registration will occur if profile 'p1' is active ORif profile 'p2' is not active.

@Profile({"p1", "!p2"}),如果配置文件 'p1' 处于活动状态配置文件 'p2' 未处于活动状态,则会进行注册。

My question is :How can we skip registration of the configurations of both profiles? @Profile({"!p1", "!p2"})is doing OR operation. We need AND operation here.

我的问题是:我们如何跳过注册两个配置文件的配置?@Profile({"!p1", "!p2"})正在做 OR 运算。我们这里需要 AND 操作。



The code :

代码 :

@Configuration
@Profile({ "!" + Constants.PROFILE_CONSOLE  })
public class MyConfigurationA {
    static{
        System.out.println("MyConfigurationA registering...");
    }
}

@Configuration
@Profile({ "!" + Constants.PROFILE_CONSOLE ,  "!" + Constants.PROFILE_DEVELOPMENT }) // doesn't exclude both, its OR condition
public class MyConfigurationB {
    static{
        System.out.println("MyConfigurationB registering...");
    }
}

public final class Constants {
    public static final String PROFILE_DEVELOPMENT = "dev";
    public static final String PROFILE_CONSOLE = "console";
    ...
}

回答by Cyril

@Profile({"!console", "!dev"})means (NOT console) OR(NOT dev) which is true if you run your app with the profile 'console'.
To solve this you can create a custom Condition:

@Profile({"!console", "!dev"})表示 (NOT console) OR(NOT dev) 如果您使用配置文件“控制台”运行您的应用程序,则为 true。
要解决此问题,您可以创建自定义Condition

public class NotConsoleAndDevCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        return !environment.acceptsProfiles("console", "dev");
    }
}

And apply the condition via the @Conditionalannotation to the Configuration:

并通过@Conditional注释将条件应用于配置:

@Conditional(NotConsoleAndDevCondition.class)
public class MyConfigurationB {

回答by Makoto

With newer versions of Spring, the acceptsProfilesmethod which accepts strings has been deprecated.

在较新版本的 Spring 中,acceptsProfiles接受字符串的方法已被弃用。

To do the equivalent work as in Cyril's question, you would need to leverage the new method parameter. This newer format also gives you the flexibility to author profile expressions which are more powerful than what was in place prior, thus eliminating the need to negate the entire acceptsProfilesexpression itself.

要执行与Cyril 的问题相同的工作,您需要利用新方法参数。这种较新的格式还使您可以灵活地创作比以前更强大的配置文件表达式,从而消除了否定整个acceptsProfiles表达式本身的需要。

public class NotConsoleAndDevCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        return environment.acceptsProfiles(Profiles.of("!console & !dev"));
    }
}

回答by xyz

Starting with Spring 5.1 you can use expressionsin @Profileannotation. Read more in the @Profile documentation. Example:

从 Spring 5.1 开始,您可以在注释中使用表达式@Profile。在@Profile 文档中阅读更多内容。例子:

@Configuration
@Profile({ "!console & !dev" }) 
public class MyConfigurationB {
    static{
        System.out.println("MyConfigurationB registering...");
    }
}