Spring Cloud Config
application.yml 和 bootstrap.yml 區別
加載順序
- bootstrap.yml 先加載
- application.yml 後加載
bootstrap.yml 用於應用程序上下文的引導階段。
bootstrap.yml 由父 Spring ApplicationContext 加載。
父ApplicationContext被加載到使用application.yml 的之前
配置區別
bootstrap.yml 和 application.yml 都可以用來配置參數
- bootstrap.yml 可以理解爲系統級別的一些參數配置,這些參數一般是不會變動的。
- application.yml 可以用來定義應用節級別的,如果搭配 spring-cloud-config 使用application.yml 裏面定義的文件可以實現動態替換。 使用Stpring Cloud Config Server時,應在bootstrap.yml 中指定:
- spring.application.name
- spring.cloud.config.server.git.url
- 一些加密/解密信息
application 的加載原理
啓動上下文
Spring Cloud 會創建一個Bootstrap Context
,作爲Spring應用的Application Context
的父上下文。初始化的時候,Bootstrap Context
複製從外部源加載配置屬性並解析配置。 這兩個上下文共享一個從外部獲取的Environment
.Bootstrap
屬性有高優先級,默認情況下,它們不會被本地配置覆蓋。Bootstrap context
和 Application Context
有着不同的約定,所有新增了一個bootstrap.yml
文件,而不是使用application.yml
。保證Bootstarp Context
和 Application Context
配置的分離。
應用上下文層次結構
如果你通過 SpringApplicaion
或者 SpringApplicationBuilder
創建一個Application Context
,那麼會爲spring應用的Application Context
創建父上下文Bootstrap Context
。在Spring裏有個特性,子上下文會繼承父類的property sources
,會新增額外的property sources
。額外的property sources
有:
- “bootstrap”: 如果在Boostrap Context 掃描到PropertySourceLocator並且有屬性,則會添加到CompositePropertySource.Spring Cloud COnfig 就是通過這種方式來添加屬性,詳情請查看源碼 ConfigServicePropertySourceLocator。
- “applicationConfig:[classpath:bootstrap.yml]” (如果有 spring.profiles.active=production,則例如 applicationConfig:[classpath:/bootstrap.yml]#product): 如果你是用bootstrap.yml 來配置Bootstrap Context,他比application.yml 優先級別要低,它將添加到子上下文,作爲Spring Boot 應用程序的一部分。
由於優先級規則,Bootstrap Context 不包含從Bootstrap.yml 來的數據,但可以用它作爲默認設置。
你可以很容易的擴展任何你建立的上下文層次,可以使用它提供的接口,或者使用 SpringApplicationBuillder包含的方法(parent(),child(),sibling())。 Bootstrap Context 將是最高級別的父類。擴展的每一個Context都有自己的 bootstrap property source(有可能是空的)。擴展的每一個Context 都有不同 spring.application.name。 同一層層次的父子上下文原則上也有着不同的名稱,因此,也會有不同的Config Server配置。子上下文的屬性在相同名字的情況下將覆蓋父上下文的屬性。
注意:SpringApplicationBuilder允許共享Environment到所有層次,但是不是默認的。 因此,同級的兄弟上下文不在和父類共享一些東西的時候不一定有相同的profiles或者property sources。
修改Bootstrap屬性配置
源碼位置: BootstrapApplicationLister
String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
Map<String, Object> bootstrapMap = new HashMap<>();
bootstrapMap.put("spring.config.name",configName);
if(StringUtils.hasText(configLocation)){
bootstrapMap.put("spring.config.location", configLocation);
}
bootstrap.yml 是有spring.cloud.bootstrap.name(默認:“bootstrap”) 或者 spring.cloud.bootstrap.location(默認空)。這些屬性行爲與spring.config.* 類似,通過它的Environment來配置引導ApplicationContext。如果有一個激活的profile(來源與 spring.profiles.active 或者 Environment 的Api構建),例如 bootstrap-development.properies 就是配置了 profile爲development的配置文件。
覆蓋遠程屬性
property sources 被bootstrap context添加到應用通常遠程的方式,比如“Config Server”。默認情況下,本地的配置文件不能覆蓋遠程配置,但是可以通過啓動命令參數來覆蓋遠程配置。如果需要本地文件覆蓋遠程文件,需要在遠程配置文件裏設置 spring.cloud.config.allowOverride=true
(這個配置不能在本地被設置)。一旦設置了這個權限,你可以配置更加細粒度的配置來配置覆蓋的方式。
spring.cloud.config.overrideNoe = true #覆蓋任何本地屬性
spring.cloud.config.overrideSystemProperties=false #僅僅系統屬性和環境變量
源文件詳見 PropertySourceBootstrapProperties
自定義啓動配置
bootstrap context 是依賴 /META-INF/spring.factories 文件裏面的 org.springframework.cloud.bootstrap.BootstrapConfiguration 條目下面,通過逗號分隔的Spring @Configuration 類來建立的配置。任何main application context 需要自動注入的Bean可以在這裏通過這種方式獲取。這也是 ApplicationContextInitializer 建立@Bean的方式。可以通過 @Order來更改初始化序列,默認是"last"。
# spring-cloud-context-1.1.1.RELEASE.jar
# spring.factories
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration
# Application Listeners
org.springframework.context.ApplicationListener=\org.springframework.cloud.bootstrap.BootstrapApplicationListener,org.springframework.cloud.context.restart.RestartListener
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration
你添加的自定義BootstrapConfiguration類沒有錯誤的@ComponentScanned到你的主應用上下文,他們可能是不需要的。使用一個另外的包不被@ComponentScan或者@SpringBootApplication註解覆蓋到。
bootstrap context 通過 spring.factories 的配置類初始化所有的Bean都會在SpringApplication啓動前加入到它的上下文裏去。
自定義引導配置來源: Bootstrap Property Sources
默認的property source
添加額外的配置是通過配置服務(Config Server),你也可以自定義添加 property soruce
通過實現 PropertySourceLocator
接口來添加。你可以使用它加配置屬從不同的服務,數據庫或者其他。
demo:
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("customProperty", Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}
Environment 被 ApplicationContext建立,並傳入 property sources(可能不同的profile有不同的屬性),所以,你可以從Environment尋找找一些特別的屬性。比如spring.application.name,它是默認的Config Server property source。
如果你建立了一個jar包,裏面添加了一個 META-INF/spring.factories文件:org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
。那麼“CostomProperty” 的
參考資料
(SpringCloud入門之常用的配置文件 application.yml和 bootstrap.yml區別)[https://www.cnblogs.com/BlogNetSpace/p/8469033.html]
(Spring Boot)[https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/]
(Spring Boot)[https://github.com/spring-projects/spring-boot]