Spring Profiles – 春季简介

最后修改: 2014年 11月 9日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll focus on introducing Profiles in Spring.

在本教程中,我们将重点介绍Spring中的Profiles。

Profiles are a core feature of the framework — allowing us to map our beans to different profiles — for example, dev, test, and prod.

配置文件是框架的一个核心功能–允许我们将我们的Bean映射到不同的配置文件中–例如,devtest,和prod

We can then activate different profiles in different environments to bootstrap only the beans we need.

然后我们可以在不同的环境中激活不同的配置文件,只启动我们需要的豆子。

2. Use @Profile on a Bean

2.在一个Bean上使用@Profile

Let’s start simple and look at how we can make a bean belong to a particular profile. We use the @Profile annotation — we are mapping the bean to that particular profile; the annotation simply takes the names of one (or multiple) profiles.

让我们从简单的开始,看看我们如何使一个bean属于一个特定的配置文件。我们使用@Profile注解–我们将bean映射到那个特定的profile;该注解仅仅是接受一个(或多个)profile的名称。

Consider a basic scenario: We have a bean that should only be active during development but not deployed in production.

考虑一个基本场景。我们有一个Bean,它只应该在开发期间活动,但不应该在生产中部署。

We annotate that bean with a dev profile, and it will only be present in the container during development. In production, the dev simply won’t be active:

我们用dev配置文件来注释该Bean,它将只在开发期间出现在容器中。在生产中,dev根本不会被激活。

@Component
@Profile("dev")
public class DevDatasourceConfig

As a quick sidenote, profile names can also be prefixed with a NOT operator, e.g., !dev, to exclude them from a profile.

作为一个快速的附带说明,配置文件名称也可以用NOT操作符作为前缀,例如,!dev,以将其从配置文件中排除。

In the example, the component is activated only if dev profile is not active:

在这个例子中,只有当dev配置文件未被激活时,该组件才被激活。

@Component
@Profile("!dev")
public class DevDatasourceConfig

3. Declare Profiles in XML

3.在XML中声明配置文件

Profiles can also be configured in XML. The <beans> tag has a profile attribute, which takes comma-separated values of the applicable profiles:

配置文件也可以在XML中配置。<beans>标签有一个profile属性,它采用逗号分隔的适用配置文件的值。

<beans profile="dev">
    <bean id="devDatasourceConfig" 
      class="org.baeldung.profiles.DevDatasourceConfig" />
</beans>

4. Set Profiles

4.设置配置文件

The next step is to activate and set the profiles so that the respective beans are registered in the container.

下一步是激活和设置配置文件,以便在容器中注册各自的豆子。

This can be done in a variety of ways, which we’ll explore in the following sections.

这可以通过各种方式进行,我们将在以下章节中探讨。

4.1. Programmatically via WebApplicationInitializer Interface

4.1.通过WebApplicationInitializer接口进行编程

In web applications, WebApplicationInitializer can be used to configure the ServletContext programmatically.

在Web应用程序中,WebApplicationInitializer可用于以编程方式配置ServletContext

It’s also a very handy location to set our active profiles programmatically:

这也是一个非常方便的位置,可以通过程序设置我们的活动档案。

@Configuration
public class MyWebApplicationInitializer 
  implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
 
        servletContext.setInitParameter(
          "spring.profiles.active", "dev");
    }
}

4.2. Programmatically via ConfigurableEnvironment

4.2.通过ConfigurableEnvironment进行编程。

We can also set profiles directly on the environment:

我们还可以直接在环境上设置配置文件。

@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");

4.3. Context Parameter in web.xml

4.3.web.xml中的上下文参数

Similarly, we can define the active profiles in the web.xml file of the web application, using a context parameter:

同样,我们可以在Web应用程序的web.xml文件中使用上下文参数定义活动配置文件。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>dev</param-value>
</context-param>

4.4. JVM System Parameter

4.4.JVM系统参数

The profile names can also be passed in via a JVM system parameter. These profiles will be activated during application startup:

配置文件名称也可以通过JVM系统参数传入。这些配置文件将在应用程序启动时被激活。

-Dspring.profiles.active=dev

4.5. Environment Variable

4.5.环境变量

In a Unix environment, profiles can also be activated via the environment variable:

在Unix环境中,配置文件也可以通过环境变量激活

export spring_profiles_active=dev

4.6. Maven Profile

4.6.Maven简介

Spring profiles can also be activated via Maven profiles, by specifying the spring.profiles.active configuration property.

通过指定spring.profiles.active configuration属性,Spring配置文件也可以通过Maven配置文件来激活。

In every Maven profile, we can set a spring.profiles.active property:

在每个Maven配置文件中,我们都可以设置一个spring.profiles.active属性。

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profiles.active>dev</spring.profiles.active>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
    </profile>
</profiles>

Its value will be used to replace the @spring.profiles.active@ placeholder in application.properties:

它的值将被用来替换@spring.profiles.active@ application.properties中的占位符:

spring.profiles.active=@spring.profiles.active@

Now we need to enable resource filtering in pom.xml:

现在我们需要在pom.xml中启用资源过滤功能。

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    ...
</build>

and append a -P parameter to switch which Maven profile will be applied:

并附加一个-P参数,以切换将应用的Maven配置文件。

mvn clean package -Pprod

This command will package the application for prod profile. It also applies the spring.profiles.active value prod for this application when it is running.

这个命令将为prod配置文件打包应用程序。它还会在该应用程序运行时为其应用spring.profiles.activeprod

4.7. @ActiveProfile in Tests

4.7.@ActiveProfile在测试中

Tests make it very easy to specify what profiles are active using the @ActiveProfile annotation to enable specific profiles:

测试使指定哪些配置文件是活动的非常容易,使用@ActiveProfile注解来启用特定的配置文件。

@ActiveProfiles("dev")

So far, we’ve looked at multiple ways of activating profiles. Let’s now see which one has priority over the other and what happens if we use more than one, from highest to lowest priority:

到目前为止,我们已经看了激活配置文件的多种方式。现在让我们看看哪种方式比另一种方式有优先权,以及如果我们使用多种方式,从高到低的优先权会发生什么。

  1. Context parameter in web.xml
  2. WebApplicationInitializer
  3. JVM System parameter
  4. Environment variable
  5. Maven profile

5. The Default Profile

5.默认配置文件

Any bean that does not specify a profile belongs to the default profile.

任何没有指定配置文件的bean都属于default配置文件。

Spring also provides a way to set the default profile when no other profile is active — by using the spring.profiles.default property.

Spring还提供了一种方法,当没有其他配置文件处于活动状态时,可以通过使用spring.profiles.default属性设置默认配置文件。

6. Get Active Profiles

6.获得活跃的配置文件

Spring’s active profiles drive the behavior of the @Profile annotation for enabling/disabling beans. However, we may also wish to access the list of active profiles programmatically.

Spring的活动配置文件驱动@Profile注解的行为,用于启用/禁用Bean。然而,我们也可能希望以编程方式访问活动配置文件的列表。

We have two ways to do it, using Environment or spring.profiles.active.

我们有两种方法,使用Environment spring.profiles.active

6.1. Using Environment

6.1.使用环境

We can access the active profiles from the Environment object by injecting it:

我们可以通过注入Environment对象来访问活动配置文件。

public class ProfileManager {
    @Autowired
    private Environment environment;

    public void getActiveProfiles() {
        for (String profileName : environment.getActiveProfiles()) {
            System.out.println("Currently active profile - " + profileName);
        }  
    }
}

6.2. Using spring.profiles.active

6.2.使用spring.profiles.active

Alternatively, we could access the profiles by injecting the property spring.profiles.active:

另外,我们可以通过注入属性spring.profiles.active来访问这些配置文件。

@Value("${spring.profiles.active}")
private String activeProfile;

Here, our activeProfile variable will contain the name of the profile that is currently active, and if there are several, it’ll contain their names separated by a comma.

在这里,我们的activeProfile变量将包含当前激活的配置文件的名称,如果有几个,它将包含用逗号分隔的名称。

However, we should consider what would happen if there is no active profile at all. With our code above, the absence of an active profile would prevent the application context from being created. This would result in an IllegalArgumentException owing to the missing placeholder for injecting into the variable.

然而,我们应该考虑如果根本没有活动的配置文件会发生什么。在我们上面的代码中,没有活动的配置文件将阻止应用程序上下文被创建。这将导致IllegalArgumentException,因为缺少用于注入变量的占位符。

In order to avoid this, we can define a default value:

为了避免这种情况,我们可以定义一个默认值

@Value("${spring.profiles.active:}")
private String activeProfile;

Now, if no profiles are active, our activeProfile will just contain an empty string.

现在,如果没有配置文件被激活,我们的activeProfile将只包含一个空字符串。

And if we want to access the list of them just like in the previous example, we can do it by splitting the activeProfile variable:

而如果我们想像前面的例子那样访问它们的列表,我们可以通过splitting变量activeProfile来实现。

public class ProfileManager {
    @Value("${spring.profiles.active:}")
    private String activeProfiles;

    public String getActiveProfiles() {
        for (String profileName : activeProfiles.split(",")) {
            System.out.println("Currently active profile - " + profileName);
        }
    }
}

7. Example: Separate Data Source Configurations Using Profiles

7.示例。使用配置文件分离数据源配置

Now that the basics are out of the way, let’s take a look at a real example.

现在基础知识已经讲完了,让我们来看看一个真实的例子。

Consider a scenario where we have to maintain the data source configuration for both the development and production environments.

考虑这样一种情况:我们必须为开发和生产环境维护数据源配置

Let’s create a common interface DatasourceConfig that needs to be implemented by both data source implementations:

让我们创建一个共同的接口DatasourceConfig,需要由两个数据源的实现来实现。

public interface DatasourceConfig {
    public void setup();
}

Following is the configuration for the development environment:

以下是开发环境的配置。

@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {
    @Override
    public void setup() {
        System.out.println("Setting up datasource for DEV environment. ");
    }
}

And configuration for the production environment:

并为生产环境进行配置。

@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {
    @Override
    public void setup() {
       System.out.println("Setting up datasource for PRODUCTION environment. ");
    }
}

Now let’s create a test and inject our DatasourceConfig interface; depending on the active profile, Spring will inject DevDatasourceConfig or ProductionDatasourceConfig bean:

现在让我们创建一个测试并注入我们的DatasourceConfig接口;根据活动配置文件,Spring将注入DevDatasourceConfigProductionDatasourceConfigbean。

public class SpringProfilesWithMavenPropertiesIntegrationTest {
    @Autowired
    DatasourceConfig datasourceConfig;

    public void setupDatasource() {
        datasourceConfig.setup();
    }
}

When the dev profile is active, Spring injects DevDatasourceConfig object, and when calling then setup() method, the following is the output:

dev配置文件被激活时,Spring注入了DevDatasourceConfig对象,当调用setup()方法时,输出如下。

Setting up datasource for DEV environment.

8. Profiles in Spring Boot

8.Spring Boot中的配置文件

Spring Boot supports all the profile configuration outlined so far, with a few additional features.

Spring Boot支持到目前为止概述的所有配置文件配置,还有一些额外的功能。

8.1. Activating or Setting a Profile

8.1.激活或设置一个配置文件

The initialization parameter spring.profiles.active, introduced in Section 4, can also be set up as a property in Spring Boot to define currently active profiles. This is a standard property that Spring Boot will pick up automatically:

第4节中介绍的初始化参数spring.profiles.active也可以在Spring Boot中设置为一个属性,以定义当前活跃的配置文件。这是一个标准属性,Spring Boot会自动拾取。

spring.profiles.active=dev

However, starting Spring Boot 2.4, this property cannot be used in conjunction with spring.config.activate.on-profile, as this could raise a ConfigDataException (i.e. an InvalidConfigDataPropertyException or an InactiveConfigDataAccessException).

然而,从Spring Boot 2.4开始,该属性不能与spring.config.activated.on-profile一起使用,因为这可能引发ConfigDataExceptionInvalidConfigDataPropertyExceptionInactiveConfigDataAccessException)。

To set profiles programmatically, we can also use the SpringApplication class:

为了以编程方式设置配置文件,我们也可以使用SpringApplication类。

SpringApplication.setAdditionalProfiles("dev");

To set profiles using Maven in Spring Boot, we can specify profile names under spring-boot-maven-plugin in pom.xml:

要在Spring Boot中使用Maven设置配置文件,我们可以在pom.xml中的spring-boot-maven-plugin下指定配置文件名称。

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <profiles>
                <profile>dev</profile>
            </profiles>
        </configuration>
    </plugin>
    ...
</plugins>

and execute the Spring Boot-specific Maven goal:

并执行Spring Boot专用的Maven目标。

mvn spring-boot:run

8.2. Profile-specific Properties Files

8.2.特定配置文件的属性文件

However, the most important profiles-related feature that Spring Boot brings is profile-specific properties files. These have to be named in the format application-{profile}.properties.

然而,Spring Boot带来的最重要的配置文件相关功能是配置文件特定的属性文件。这些文件必须以application-{profile}.properties格式命名。

Spring Boot will automatically load the properties in an application.properties file for all profiles, and the ones in profile-specific .properties files only for the specified profile.

Spring Boot将为所有配置文件自动加载application.properties文件中的属性,而只为指定的配置文件加载特定的.properties文件中的属性。

For example, we can configure different data sources for dev and production profiles by using two files named application-dev.properties and application-production.properties:

例如,我们可以通过使用名为application-dev.propertiesapplication-production.properties的两个文件,为devproduction配置文件配置不同的数据源。

In the application-production.properties file, we can set up a MySql data source:

application-production.properties文件中,我们可以设置一个MySql数据源。

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root

Then we can configure the same properties for the dev profile in the application-dev.properties file, to use an in-memory H2 database:

然后我们可以在application-dev.properties文件中为dev配置文件配置相同的属性,以使用内存中的H2数据库。

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

In this way, we can easily provide different configurations for different environments.

通过这种方式,我们可以轻松地为不同的环境提供不同的配置。

Prior to Spring Boot 2.4, it was possible to activate a profile from profile-specific documents. But that is no longer the case; with later versions, the framework will throw – again – an InvalidConfigDataPropertyException or an InactiveConfigDataAccessException in these circumstances.

在Spring Boot 2.4之前,可以从特定的配置文件文件中激活一个配置文件。但现在已经不是这样了;在后来的版本中,框架会在这些情况下再次抛出InvalidConfigDataPropertyExceptionInactiveConfigDataAccessException

8.3. Multi-Document Files

8.3.多文档文件

To further simplify defining properties for separate environments, we can even club all the properties in the same file and use a separator to indicate the profile.

为了进一步简化为不同环境定义的属性,我们甚至可以将所有的属性分在同一个文件中,并使用一个分隔符来表示配置文件。

Starting version 2.4, Spring Boot has extended its support for multi-document files for properties files in addition to previously supported YAML. So now, we can specify the dev and production properties in the same application.properties:

从 2.4 版开始,除了之前支持的 YAML 外,Spring Boot 还扩展了对属性文件的多文档文件支持。所以现在,我们可以在同一个application.properties中指定devproduction属性。

my.prop=used-always-in-all-profiles
#---
spring.config.activate.on-profile=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
#---
spring.config.activate.on-profile=production
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

This file is read by Spring Boot in top to bottom order. That is, if some property, say my.prop, occurs once more at the end in the above example, the endmost value will be considered.

Spring Boot是按照从上到下的顺序读取这个文件的。也就是说,如果某个属性,例如my.prop,在上例中最后再出现一次,就会考虑最末尾的值。

8.4. Profile Groups

8.4.简介组

Another feature added in Boot 2.4 is Profile Groups. As the name suggests, it allows us to group similar profiles together.

Boot 2.4中增加的另一个功能是Profile Groups。顾名思义,它允许我们将类似的配置文件分组

Let’s consider a use case where we’d have multiple configuration profiles for the production environment. Say, a proddb for the database and prodquartz for the scheduler in the production environment.

让我们考虑一个用例,我们为生产环境准备了多个配置文件。例如,在生产环境中,数据库的proddb和调度器的prodquartz

To enable these profiles all at once via our application.properties file, we can specify:

要通过我们的application.properties文件一次性启用这些配置文件,我们可以指定。

spring.profiles.group.production=proddb,prodquartz

Consequently, activating the production profile will activate proddb and prodquartz as well.

因此,激活production配置文件将同时激活proddbprodquartz

9. Conclusion

9.结论

In this article, we discussed how to define a profile on a bean and how to then enable the right profiles in our application.

在这篇文章中,我们讨论了如何在Bean上定义配置文件,以及如何在我们的应用程序中启用正确的配置文件

Finally, we validated our understanding of profiles with a simple but real-world example.

最后,我们用一个简单但真实的例子验证了我们对配置文件的理解。

The implementation of this tutorial can be found in the GitHub project.

本教程的实现可以在GitHub项目中找到