1. Spring Cloud Context: Application Context Services(應用上下文服務)
1.1 The Bootstrap Application 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)來添加額外的資源。
舉個?:
1 @Configuration 2 public class CustomPropertySourceLocator implements PropertySourceLocator { 3 4 @Override 5 public PropertySource<?> locate(Environment environment) { 6 return new MapPropertySource("customProperty", 7 Collections.<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: 2 endpoints: 3 web: 4 exposure: 5 include: 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也會被禁止。
?