spring cloud連載第一篇之bootstrap context
一個spring cloud應用會建立一個“bootstrap”context,它是主應用的parent context。它負責載入外部資源的配置屬性並且解釋本地外部配置檔案中的屬性。
這裡有兩個context,一個是spring boot的main context,另一個是spring cloud的bootstrap context,這兩個context共享同一個環境,也就是說他們共享spring專案的外部配置屬性。
預設情況下,bootstrap屬性(並非是bootstrap.properties而是那些在bootstrap階段載入的屬性)是以高優先順序的方式新增的,所以無法被本地配置覆蓋。
bootstrap context和main context使用不同的方法定位外部配置,你可以使用bootstrap.yml來替代application.yml來為bootstrap context新增配置,這樣就可以區分開bootstrap context和main context。
可以通過在系統屬性中設定spring.cloud.bootstrap.enabled=false來禁用bootstrap程式。
1.2 Application Context Hierarchies(應用上下文層級)
如果你通過SpringApplication或者SpringApplicationBuilder構建了一個application context,那麼bootstrap context將會作為它的parent context被新增。
spring的一個特性是child context會從它的parent context中繼承屬性資源和配置檔案,因此main application context有一些額外的屬性資源:
“bootstrap”:如果在bootstrap context中發現PropertySourceLocators並且含有非空屬性,那麼一個CompositePropertySource將會以高優先順序出現。
“applicationConfig”:如果你有一個bootstrap.yml,並且設定了配置bootstrap context的屬性,那麼它們將會被新增到child context中。但是它們具有比application.yml或者其他配置更低的優先順序。
由於資源屬性的排序規則,“bootstrap”入口具有高優先順序。注意這不包括bootstrap.yml中的資料(具有較低優先順序,可以用來設定預設屬性)。
1.3 Changing the Location of Bootstrap Properties
bootstrap.yml可以通過在系統屬性中設定spring.cloud.bootstrap.name或者spring.cloud.bootstrap.location來指定。
如果有一個啟用的配置檔案(通過spring.profiles.active或者Environment API設定),那麼這些檔案中的屬性都會被載入。
1.4 Overriding the Values of Remote Properties(覆蓋遠端屬性的值)
通過bootstrap context新增到應用中的屬性資源可能經常是“遠端”的,例如從Spring Cloud Config Server讀取的屬性。預設情況下,他們不能被本地覆蓋。
如果你希望讓你的應用通過系統屬性或者本地配置來重寫那些遠端配置,可以通過設定遠端屬性資源spring.cloud.config.allowOverride=true(在本地設定無效)。
一旦設定了上面的標誌,就可以通過下面兩個遠端屬性來控制遠端屬性和系統屬性跟本地配置的關係:
spring.cloud.config.overrideNone=true:遠端屬性可以被本地任意屬性資源覆蓋
spring.cloud.config.overrideSystemProperties=false:僅僅系統屬性,命令列引數和環境變數(不包括配置檔案)可以覆蓋遠端設定。
1.5 Customizing the Bootstrap Configuration(自定義bootstrap配置)
bootstrap context可以被設定來做任何你想要做的事,只要在/META-INF/spring.factories檔案中配置org.springframework.cloud.bootstrap.BootstrapConfiguration的值即可。
它的值是以逗號分隔的@Configuration類的全限定名。所以任何你想要在main application context中注入的bean都可以在這裡配置。如果你希望控制啟動順序,在類上新增@Order註解(預設順序為最後)。
注意:不要bootstrap配置被main context載入到,即不能被@ComponentScan和@SpringBootApplication註解的配置類覆蓋到。
bootstrap程式最後將初始化器注入到main SpringApplication例項中。首先,通過spring.factories中配置的類來建立bootstrap context,然後所有ApplicationContextInitializer的bean將會被新增到main SpringApplication中,在其啟動前。
1.6 Customizing the Bootstrap Property Sources(定製化bootstrap屬性資源)
通過bootstrap程式新增的外部配置的預設屬性資源是Spring Cloud Config Server。但是可以通過新增PropertySourceLocator型別的bean到bootstrap context中(通過spring.factories)來新增額外的資源。
舉個:chestnut::
1 @Configuration 2 public class CustomPropertySourceLocator implements PropertySourceLocator { 3 4@Override 5public PropertySource<?> locate(Environment environment) { 6return new MapPropertySource("customProperty", 7Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended")); 8} 9 10 }
然後在META-INF/spring.factories
檔案中新增
1 org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
1.7 Refresh Scope(重新整理域)
當配置改變時,被標記為@RefreshScope的bean會得到一些特殊對待。這個特性將會解決一些beans在僅僅在初始化時注入配置的問題。
例如,資料庫url改變時,資料來源已經打開了一些資料庫連線,你可能希望那些已經開啟的連線能夠將他們的工作完成,但是當有新的請求來獲取連線時,返回給他們新的url連線。
有時可能需要強制性的在一些只能初始化一次的bean上新增@RefreshScope註解。如果一個bean是“不可變的”,你將不得不為它新增@RefreshScope註解或者在spring.cloud.refresh.extra-refreshable鍵上指定class name。
處在refresh scope中的bean是延遲代理,只有當他們被使用時才初始化,並且這個scope像是一個已初始化值的快取。為了能使bean在下次使用時重新初始化,必須將它的快取入口置為無效。
RefreshScope是一個bean,並且有一個公共方法refreshAll(),這個方法通過清理目標快取的手段來達到重新整理在scope中的所有bean。
端點/refresh向外部提供了這個功能(通過HTTP或者JMX)。如果想通過bean的名稱來重新整理bean可以使用refresh(String)方法。
要向外暴露/refresh端點,需要在配置檔案中寫入以下配置:
1 management: 2endpoints: 3web: 4exposure: 5include: refresh
注意:@RefreshScope在@Configuration的類上起作用,但可能有一些特殊的行為。比如說,並不意味著所有在@Configuration類中定義的bean都是在@RefreshScope中的。所以任何依賴那些bean的東西都不能在重新整理時得到
更新。
1.8 Endpoints(端點)
如果你的應用是一個Spring Boot Actuator 那麼會有一些額外的管理端點:
傳送一個POST請求到/actuator/env可以更新Environment,重新繫結@ConfigurationProperties
和日誌級別;
/actuator/refresh重新載入bootstrap context並且重新整理@RefreshScope中的bean;
/actuator/restart重新啟動ApplicationContext(預設此功能是關閉的);
/actuator/pause和/actuator/resume是在ApplicationContext上呼叫生命週期方法stop()和start()
注意:如果禁止了/actuator/restart端點那麼/actuator/pause和/actuator/resume也會被禁止。