Profile的意思是配置,對於應用程序來講,不一樣的環境須要不一樣的配置。
好比:javascript
Spring框架提供了多profile的管理功能,咱們可使用profile功能來區分不一樣環境的配置。html
首先,咱們先看看如何基於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); } } }
接下來,爲了讓容器"僅僅註冊那些所須要的Bean",咱們須要經過一些手段來設置當前的profile。數據庫
有不少方法能夠達到這個目的,下面一一介紹。bash
在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"); } }
與上面的方法相似,在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>
經過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
在Unix/Linux環境中,能夠經過環境變量注入profile的值:
export spring_profiles_active=dev java -jar application.jar
能夠在application.properties配置文件中指定spring.profiles.active屬性:
spring.profiles.active=dev
SpringBoot默認會加載並讀取該配置,當發現爲profile=dev時,會同時關聯加載application-dev.properties這個配置。
這種方式很是簡單,能夠實現對不一樣環境採用單獨的配置文件進行隔離。
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
@ActiveProfile 是用於單元測試場景的註解,能夠爲測試代碼指定一個隔離的profile,以下:
@ActiveProfiles("test") public void ApiTest{ ... }
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)
SpringApplication這個類還提供了setAdditionalProfiles方法,用來讓咱們實現"附加"式的profile。
這些profile會同時被啓用,而不是替換原來的active profile,以下:
SpringApplication application = new SpringApplication(MyApplication.class); application.setAdditionalProfiles("new_dev");
這種方式能夠實現無條件的啓用profile,優先級是最高的。
固然,還能夠經過設定spring.profiles.include來達到一樣的目的。
至此,咱們已經提供了不少種方法來設定 Spring應用的profile,當它們同時存在時則會根據必定優先級來抉擇,參考以下:
從上至下,優先級從高到低排列。
其中,Maven profile與配置文件的方式相同,環境變量以及JVM啓動參數會覆蓋配置文件的內容。
1和2則屬於進程內的控制邏輯,優先級更高。
若是在啓動SpringBoot應用前對當前ConfigurableEnvironment對象注入了profile,則會優先使用這個參數, ActiveProfiles用於測試環境,其原理與此相似。
SpringApplication.setAdditionalProfiles則是不管如何都會附加的profile,優先級最高。
最後,咱們在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