解惑!全面解讀 Spring Profile 的用法

1、簡介

Profile的意思是配置,對於應用程序來講,不一樣的環境須要不一樣的配置。
好比:javascript

  • 開發環境,應用須要鏈接一個可供調試的數據庫單機進程
  • 生產環境,應用須要使用正式發佈的數據庫,一般是高可用的集羣
  • 測試環境,應用只須要使用內存式的模擬數據庫

Spring框架提供了多profile的管理功能,咱們可使用profile功能來區分不一樣環境的配置。html

2、 區分Bean對象

首先,咱們先看看如何基於Profile來定義一個Bean。java

經過@Profile註解能夠爲一個Bean賦予對應的profile名稱,以下:nginx

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

上面的DevDatasourceConfig被定義爲 profile=dev,因而該Bean只會在dev(開發環境)模式下被啓用。
若是須要定義爲非dev環境,可使用這樣的形式:web

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

XML風格配置
上面的例子也可使用XML配置文件達到一樣的目的,以下:spring

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

讀取Profile
經過ConfigurableEnvironment這個Bean 能夠得到當前的Profile,以下:shell

public class ProfileManager { @Autowired Environment environment; public void getActiveProfiles() { for (final String profileName : environment.getActiveProfiles()) { System.out.println("Currently active profile - " + profileName); } } }

3、 設置Profile

接下來,爲了讓容器"僅僅註冊那些所須要的Bean",咱們須要經過一些手段來設置當前的profile。數據庫

有不少方法能夠達到這個目的,下面一一介紹。bash

3.1 WebApplicationInitializer接口

在Web應用程序中,經過WebApplicationInitializer能夠對當前的ServletContext進行配置。app

以下,經過注入spring.profiles.active變量能夠爲Spring上下文指定當前的 profile:

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

3.2 經過 web.xml定義

與上面的方法相似,在web.xml中經過context-param元素也能夠設置profile。

但前提是當前應用程序使用了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>

3.3 JVM啓動參數

經過Java程序啓動參數一樣能夠對profile進行設定,以下:

java -jar application.jar -Dspring.profiles.active=dev 

spring-boot-maven-plugin插件也支持設定profile,其原理也是經過啓動參數實現,能夠參考這裏

https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/run-profiles.html

3.4 環境變量

在Unix/Linux環境中,能夠經過環境變量注入profile的值:

export spring_profiles_active=dev java -jar application.jar 

3.5 application.properties

能夠在application.properties配置文件中指定spring.profiles.active屬性:

spring.profiles.active=dev

SpringBoot默認會加載並讀取該配置,當發現爲profile=dev時,會同時關聯加載application-dev.properties這個配置。
這種方式很是簡單,能夠實現對不一樣環境採用單獨的配置文件進行隔離。

3.6 Maven Profile

Maven自己也提供了Profile的功能,能夠經過Maven的Profile配置來指定Spring的Profile。

這種作法稍微有點複雜,須要先在pom.xml中設定不一樣的 maven profile,以下:

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

這裏,分別聲明瞭dev和prod兩個profile,每一個profile都包含了一個spring.profiles.active屬性,這個屬性用來注入到 Spring中的profile入參。
在SpringBoot的配置文件application.properties中,須要替換爲這個maven傳入的property:

## 使用Maven的屬性進行替換 spring.profiles.active=@spring.profiles.active@

接下來,須要讓Maven在打包時能將application.properties進行過濾處理,同時替換掉變量,需編輯pom.xml以下:

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

這裏定義了filtering=true,所以Resource打包插件會對配置文件執行過濾。

若是你的項目pom定義繼承自 spring-boot-starter-parent,那麼能夠不須要配置這個filter

最後,在maven打包時指定參數以下:

mvn clean package -Pprod

3.7 使用 @ActiveProfiles

@ActiveProfile 是用於單元測試場景的註解,能夠爲測試代碼指定一個隔離的profile,以下:

@ActiveProfiles("test") public void ApiTest{ ... }

3.8 使用 ConfigurableEnvironment

ConfigurableEnvironment 這個Bean封裝了當前環境的配置信息,你能夠在啓動應用前進行設定操做:

SpringApplication application = new SpringApplication(MyApplication.class); //設置environment中的profiler ConfigurableEnvironment environment = new StandardEnvironment(); environment.setActiveProfiles("dev","join_dev"); application.setEnvironment(environment); application.run(args)

3.9 SpringApplication.setAdditionalProfiles

SpringApplication這個類還提供了setAdditionalProfiles方法,用來讓咱們實現"附加"式的profile。
這些profile會同時被啓用,而不是替換原來的active profile,以下:

SpringApplication application = new SpringApplication(MyApplication.class); application.setAdditionalProfiles("new_dev");

這種方式能夠實現無條件的啓用profile,優先級是最高的。 
固然,還能夠經過設定spring.profiles.include來達到一樣的目的。

4、 優先級

至此,咱們已經提供了不少種方法來設定 Spring應用的profile,當它們同時存在時則會根據必定優先級來抉擇,參考以下:

  1. SpringApplication.setAdditionalProfiles
  2. ConfigurableEnvironment、@ActiveProfiles
  3. Web.xml的 context-param
  4. WebApplicationInitializer
  5. JVM 啓動參數
  6. 環境變量
  7. Maven profile、application.properties

從上至下,優先級從高到低排列。 
其中,Maven profile與配置文件的方式相同,環境變量以及JVM啓動參數會覆蓋配置文件的內容。
1和2則屬於進程內的控制邏輯,優先級更高。 
若是在啓動SpringBoot應用前對當前ConfigurableEnvironment對象注入了profile,則會優先使用這個參數, ActiveProfiles用於測試環境,其原理與此相似。
SpringApplication.setAdditionalProfiles則是不管如何都會附加的profile,優先級最高。

5、 案例

最後,咱們在SpringBoot中演示一個使用Profile的例子。

通常,在開發環境和生產環境中的數據源配置是不一樣的,藉助Profile咱們能夠定義出不一樣環境的數據源Bean。
首先咱們先建立一個接口:

public interface DatasourceConfig { public void setup(); }

對於開發環境,DatasourceConfig實現以下:

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

一樣,爲生產環境也實現一個DatasourceConfig:

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

接下來,咱們聲明一個Bean,對數據源執行初始化方法:

@Component public class SpringProfilesTest { @Autowired DatasourceConfig datasourceConfig; @PostConstruct public void setupDatasource() { datasourceConfig.setup(); } } 

以後,在application.properties的配置爲:

spring.profiles.active=dev

啓動SpringBoot 應用,發現輸出以下:

Setting up datasource for DEV environment.

此時說明dev的profile被啓用了!

參考文檔

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
http://dolszewski.com/spring/spring-boot-properties-per-maven-profile/
https://www.concretepage.com/spring-5/activeprofiles-example-spring-test
https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/run-profiles.html

相關文章
相關標籤/搜索