詳解Spring中的Environment外部化配置管理
Environment的中文意思是環(huán)境,它表示整個spring應(yīng)用運行時的環(huán)境信息,它包含兩個關(guān)鍵因素
- profiles
- properties
profiles
profiles這個概念相信大家都已經(jīng)理解了,最常見的就是不同環(huán)境下,決定當前spring容器中的不同配置上下文的解決方案。比如針對開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境,構(gòu)建不同的application.properties配置項,這個時候我們可以通過profiles這個屬性來決定當前spring應(yīng)用上下文中生效的配置項。
實際上,通過profiles可以針對bean的配置進行邏輯分組。 簡單來說,我們可以通過profiles來針對不同的bean進行邏輯分組,這個分組和bean本身的定義沒有任何關(guān)系,無論是xml還是注解方式,都可以配置bean屬于哪一個profile分組。
當存在多個profile分組時,我們可以指定哪一個profile生效,當然如果不指定,spring會根據(jù)默認的profile去執(zhí)行。我們來通過一個代碼演示一下。
ProfileService
創(chuàng)建一個普通的類,代碼如下
public class ProfileService {
private String profile;
public ProfileService(String profile) {
this.profile = profile;
}
@Override
public String toString() {
return "ProfileService{" +
"profile='" + profile + '\'' +
'}';
}
}聲明一個配置類
在配置類中,構(gòu)建兩個bean,配置不同的profile。
@Configuration
public class ProfileConfiguration {
@Bean
@Profile("dev")
public ProfileService profileServiceDev(){
return new ProfileService("dev");
}
@Bean
@Profile("prod")
public ProfileService profileServiceProd(){
return new ProfileService("prod");
}
}定義測試方法
public class ProfileMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
// applicationContext.getEnvironment().setActiveProfiles("prod");
applicationContext.register(ProfileConfiguration.class);
applicationContext.refresh();
System.out.println(applicationContext.getBean(ProfileService.class));
}
}可以通過很多種方式來激活配置,默認情況下不添加applicationContext.getEnvironment().setActiveProfiles("prod");時,會發(fā)現(xiàn)bean沒有被裝載。添加了之后,會根據(jù)當前激活的profiles來決定裝載哪個bean。
除此之外,我們還可以在啟動參數(shù)中增加-Dspring.profiles.active=prod來決定當前激活哪個profile。該屬性可以配置在系統(tǒng)環(huán)境變量、JVM系統(tǒng)屬性、等。
注意配置文件不是單選;可能會同時激活多個配置文件,編程式的使用方法setActiveProfiles(),該方法接收String數(shù)組參數(shù),也就是多個配置文件名
applicationContext.getEnvironment().setActiveProfiles("prod","dev");如果沒有任何profile配置被激活,默認的profile將會激活。 默認profile配置文件可以更改,通過環(huán)境變量的setDefaultProfiles方法,或者是聲明的spring.profiles.default屬性值
profiles總結(jié)
簡單總結(jié)一下profiles,通過profiles可以最一組bean進行邏輯分組,這些邏輯分組的bean會根據(jù)Environment上下文中配置的激活的profile來進行加載,也就是Environment對于profiles配置來說,它能決定當前激活的是哪個profile配置。
- 一個profile就是一組Bean定義的邏輯分組。
- 這個分組,也就 這個profile,被賦予一個命名,就是這個profile名字。
- 只有當一個profile處于active狀態(tài)時,它對應(yīng)的邏輯上組織在一起的這些Bean定義才會被注冊到容器中。
- Bean添加到profile可以通過XML定義方式或者annotation注解方式。
- Environment對于profile所扮演的角色是用來指定哪些profile是當前活躍的缺省。
Properties
properties的作用就是用來存放屬性的,它可以幫我們管理各種配置信息。這個配置的來源可以是properties文件、JVM properties、系統(tǒng)環(huán)境變量、或者專門的Properties對象等。
我們來看一下Environment這個接口,它繼承了PropertyResolver,這個接口和屬性的操作有關(guān),也就是我們可以通過Environment來設(shè)置和獲得相關(guān)屬性。
public interface Environment extends PropertyResolver {
String[] getActiveProfiles();
String[] getDefaultProfiles();
/** @deprecated */
@Deprecated
boolean acceptsProfiles(String... var1);
boolean acceptsProfiles(Profiles var1);
}至此,我們可以可以簡單的總結(jié)Environment的作用,Environment提供了不同的profile配置,而PropertyResolver提供了配置的操作,由此我們可以知道,Spring 容器可以根據(jù)不同的profile來獲取不同的配置信息,從而實現(xiàn)Spring容器中運行時環(huán)境的處理。
environment的應(yīng)用
在spring boot應(yīng)用中,修改application.properties配置
env=default
創(chuàng)建一個Controller進行測試
@RestController
public class EnvironementController {
@Autowired
Environment environment;
@GetMapping("/env")
public String env(){
return environment.getProperty("env");
}
}指定profile屬性
在前面的內(nèi)容中我們介紹了profile和property這兩個概念,現(xiàn)在我們來結(jié)合使用加深對這兩者的理解。
在spring boot應(yīng)用中,默認的外部化配置是application.properties文件,事實上,除了這個默認的配置文件之外,我們還可以使用springboot中的約定命名格式來實現(xiàn)不同環(huán)境的配置
application-profile.properties
當前spring boot應(yīng)用選擇使用哪個properties文件作為上下文環(huán)境配置,取決與當前激活的profile。同樣,我們可以通過很多種方式來激活,比如在application.properties中增加spring.profiles.active=dev這種方式,也可以在JVM參數(shù)中增加該配置來指定生效的配置。
在不指定的情況下,則使用默認的配置文件,簡單來說,如果沒有顯式激活某一個配置文件,那么應(yīng)用程序就將加載application-default.properties中的屬性。
這個功能非常實用,一般的公司里面都會有幾套運行環(huán)境,比如開發(fā)、測試、生產(chǎn)環(huán)境,這些環(huán)境中會有一些配置信息是不同的,比如服務(wù)器地址。那我們需要針對不同的環(huán)境使用指定的配置信息,通過這種方式就可以很方便的去解決。
@Value注解的使用
在properties文件中定義的屬性,除了可以通過environment的getProperty方法獲取之外,spring還提供了@Value注解,
@RestController
public class EnvironementController {
@Value("${env}")
private String env;
@GetMapping("/env")
public String env(){
return env;
}
}spring容器在加載一個bean時,當發(fā)現(xiàn)這個Bean中有@Value注解時,那么它可以從Environment中將屬性值進行注入,如果Environment中沒有這個屬性,則會報錯。
Spring Environment原理設(shè)計
結(jié)合前面咱們講過的內(nèi)容,我們來推測一下Environment的實現(xiàn)原理。
簡單演示一下Environment中的配置來源
- @Value("${java.version}") 獲取System.getProperties , 獲取系統(tǒng)屬性
- 配置command的jvm參數(shù),
-Denvtest=command
基于現(xiàn)有的內(nèi)容的推導,我們可以畫出下面這樣一個圖。

- 第一部分是屬性定義,這個屬性定義可以來自于很多地方,比如application.properties、或者系統(tǒng)環(huán)境變量等。
- 然后根據(jù)約定的方式去指定路徑或者指定范圍去加載這些配置,保存到內(nèi)存中。
- 最后,我們可以根據(jù)指定的key從緩存中去查找這個值。
下面這個是表示Environment的類關(guān)系圖,這個類關(guān)系圖還是非常清晰的體現(xiàn)了Environment的原理。

上述類圖的核心API說明如下
Environment接口,繼承了PropertyResolver。 PropertyResolver,它主要有兩個作用。
- 通過
propertyName屬性名獲取與之對應(yīng)的propertValue屬性值(getProperty)。 - 把
${propertyName:defaultValue}格式的屬性占位符,替換為實際的值(resolvePlaceholders)。
PropertyResolver的具體實現(xiàn)類是PropertySourcesPropertyResolver,屬性源的解決方案。該類是體系中唯一的完整實現(xiàn)類。它以PropertySources屬性源集合(內(nèi)部持有屬性源列表List )為屬性值的來源,按序遍歷每個PropertySource,獲取到一個非null的屬性值則返回。
其中,PropertySourcesPropertyResolver中的List ,表示不同屬性源的來源,它的類關(guān)系圖如下,表示針對不同數(shù)據(jù)源的存儲。

到此這篇關(guān)于詳解Spring中的Environment外部化配置管理的文章就介紹到這了,更多相關(guān)Spring Environment外部化配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot?Test的webEnvironment源碼解讀
- springboot的EnvironmentPostProcessor接口方法源碼解析
- Spring運行環(huán)境Environment的解析
- Spring?Boot讀取配置文件內(nèi)容的3種方式(@Value、Environment和@ConfigurationProperties)
- Spring之底層架構(gòu)核心概念Environment及用法詳解
- SpringBoot擴展點EnvironmentPostProcessor實例詳解
- 基于Spring Boot的Environment源碼理解實現(xiàn)分散配置詳解
- Spring之Environment類的使用方式
相關(guān)文章
String?concat(String?str)使用小結(jié)
這篇文章主要介紹了String?concat(String?str)使用小結(jié),在了解concat()之前,首先需要明確的是String的兩點特殊性,一是長度不可變二是值不可變,本文給大家詳細講解,需要的朋友可以參考下2022-11-11
SpringBoot創(chuàng)建自定義Starter代碼實例
這篇文章主要介紹了SpringBoot創(chuàng)建自定義Starter代碼實例,自定義 Starter 是一種在軟件開發(fā)中常用的技術(shù),它可以幫助開發(fā)者快速搭建項目的基礎(chǔ)框架和配置,可以將一些常用的功能、依賴和配置封裝成一個可復用的模塊,方便在不同的項目中使用,需要的朋友可以參考下2023-11-11
Java設(shè)計模式之責任鏈模式(Chain of Responsibility模式)介紹
這篇文章主要介紹了Java設(shè)計模式之責任鏈模式(Chain of Responsibility模式)介紹,本文講解了如何使用責任鏈模式,并給出了4種使用實例,需要的朋友可以參考下2015-03-03
Springboot整合Mybatis傳值的常用方式總結(jié)
今天給大家?guī)淼氖顷P(guān)于Springboot的相關(guān)知識,文章圍繞著Springboot整合Mybatis傳值的常用方式展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06
SpringCloud通過Feign傳遞List類型參數(shù)方式
這篇文章主要介紹了SpringCloud通過Feign傳遞List類型參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
java使用renderer將pdf按頁轉(zhuǎn)換為圖片
這篇文章主要為大家詳細介紹了java使用renderer將pdf按頁轉(zhuǎn)換為圖片,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12

