Spring Boot有一個關於如何使用Spring構建應用程序的主見,例如,它具備通用配置文件的常規位置,並具備用於通用管理和監控任務的端點,Spring Cloud在此基礎上構建並添加了一些功能,這些功能多是系統中的全部組件都會使用或偶爾須要的。html
Spring Cloud應用程序經過建立「bootstrap」上下文來運轉,該上下文是主應用程序的父上下文,它負責從外部源加載配置屬性以及用於解密本地外部配置文件中的屬性,這兩個上下文共享一個Environment
,它是任何Spring應用程序的外部屬性來源。默認狀況下,bootstrap屬性(不是bootstrap.properties
,而是在引導階段加載的屬性)以高優先級添加,所以本地配置沒法覆蓋它們。java
bootstrap上下文使用與主應用程序上下文不一樣的約定來定位外部配置,你可使用bootstrap.yml
而不是application.yml
(或.properties
),保持bootstrap和主上下文的外部配置很好地分開,如下清單顯示了一個示例:web
spring: application: name: foo cloud: config: uri: ${SPRING_CONFIG_URI:http://localhost:8888}
若是你的應用程序須要來自服務器的任何特定於應用程序的配置,則最好設置spring.application.name
(在bootstrap.yml
或application.yml
中)。spring
你能夠經過設置spring.cloud.bootstrap.enabled=false
來徹底禁用引導過程(例如,在系統屬性中)。sql
若是你從SpringApplication
或SpringApplicationBuilder
構建應用程序上下文,那麼Bootstrap上下文將添加爲該上下文的父級。Spring的一個特性是子上下文從其父級繼承屬性源和配置文件,所以與不使用Spring Cloud Config構建相同的上下文相比,「主」應用程序上下文包含額外的屬性源,額外的屬性源是:數據庫
PropertySourceLocators
,而且它們具備非空屬性,則會出現具備高優先級的可選CompositePropertySource
,一個例子是Spring Cloud Config Server的屬性。bootstrap.yml
(或.properties
),則這些屬性用於配置Bootstrap上下文,而後,當設置了其父級時,它們將添加到子上下文中。它們的優先級低於application.yml
(或.properties
)以及做爲建立Spring Boot應用程序過程的正常部分添加到子級的任何其餘屬性源。因爲屬性源的排序規則,「bootstrap」條目優先,但請注意,這些不包含來自bootstrap.yml
的任何數據,它具備很是低的優先級,但可用於設置默認值。bootstrap
你能夠經過設置你建立的任何ApplicationContext
的父上下文來擴展上下文層次結構 — 例如,經過使用它本身的接口或SpringApplicationBuilder
便捷方法(parent()
、child()
和sibling()
),bootstrap上下文是你本身建立的最高級祖先的父級。層次結構中的每一個上下文都有本身的「bootstrap」(多是空的)屬性源,以免無心中把父級的值傳給後代。若是存在Config Server,則層次結構中的每一個上下文(原則上)也能夠具備不一樣的spring.application.name
,所以具備不一樣的遠程屬性源。普通的Spring應用程序上下文行爲規則適用於屬性解析:來自子上下文的屬性按名稱和屬性源名稱覆蓋父級中的屬性(若是子項具備與父項具備相同名稱的屬性源,則父項中的值不包括在子項中)。segmentfault
請注意,SpringApplicationBuilder
容許你在整個層次結構中共享Environment
,但這不是默認設置,所以,兄弟上下文尤爲不須要具備相同的配置文件或屬性源,即便他們可能與父上下文共享共同的值。緩存
能夠經過設置spring.cloud.bootstrap.name
(默認值:bootstrap
)或spring.cloud.bootstrap.location
(默認值爲空)來指定bootstrap.yml
(或.properties
)位置 — 例如,在系統屬性中。這些屬性的行爲相似於具備相同名稱的spring.config.*
變體,實際上,它們用於經過在其Environment
中設置這些屬性來設置bootstrap ApplicationContext
。若是存在活動配置文件(來自spring.profiles.active
或經過你正在構建的上下文中的Environment
API),則該配置文件中的屬性也會加載,與常規Spring Boot應用程序相同 — 例如,來自bootstrap-development.properties
的development
配置文件。服務器
bootstrap上下文添加到應用程序的屬性源一般是「遠程」的(例如,來自Spring Cloud Config Server),默認狀況下,它們沒法被本地覆蓋。若是要讓應用程序使用本身的系統屬性或配置文件覆蓋遠程屬性,遠程屬性源必須經過設置spring.cloud.config.allowOverride=true
來授予它權限(它不能在本地設置它),設置該標誌後,兩個更細粒度的設置將控制遠程屬性相對於系統屬性和應用程序本地配置的位置:
spring.cloud.config.overrideNone=true
:從任何本地屬性源覆蓋。spring.cloud.config.overrideSystemProperties=false
:只有系統屬性、命令行參數和環境變量(但不是本地配置文件)才應覆蓋遠程設置。經過向/META-INF/spring.factories
下添加鍵名爲org.springframework.cloud.bootstrap.BootstrapConfiguration
的條目,能夠將bootstrap上下文設置爲執行任何操做。它包含一個以逗號分隔的用於建立上下文的Spring @Configuration
類列表,你能夠在此處建立你但願可用於主應用程序上下文以進行自動裝配的任何Bean。ApplicationContextInitializer
類型的@Beans
有一個特殊的合約,若是要控制啓動順序,可使用@Order
註解標記類(默認順序爲last
)。
添加自定義BootstrapConfiguration
時,請注意你添加的類不是@ComponentScanned
錯誤地進入你的「主」應用程序上下文,可能不須要它們。爲引導配置類使用單獨的包名稱,並確保@ComponentScan
或@SpringBootApplication
註解的配置類還沒有涵蓋該名稱。
引導過程經過將初始化器注入主SpringApplication
實例(這是正常的Spring Boot啓動順序,不管是做爲獨立應用程序運行仍是部署在應用程序服務器中)而結束,首先,從spring.factories
中的類建立bootstrap上下文,而後,全部類型爲ApplicationContextInitializer
的@Beans
在它啓動以前都會添加到主SpringApplication
中。
引導過程添加的外部配置的默認屬性源是Spring Cloud Config Server,但你能夠經過將類型爲PropertySourceLocator
的bean添加到bootstrap上下文中來添加其餘來源(經過spring.factories
),例如,你能夠從不一樣的服務器或數據庫插入其餘屬性。
例如,請考慮如下自定義locator
:
@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
的環境 — 換句話說,咱們爲其提供其餘屬性源的環境。它已經有了正常的Spring Boot提供的屬性源,所以,你可使用它們來查找特定於此Environment
的屬性源(例如,經過將其鍵入spring.application.name
,就像在默認的Spring Cloud Config Server屬性源定位器中所作的那樣)。
若是在其中建立包含此類的jar,而後添加包含如下內容的META-INF/spring.factories
,則customProperty
PropertySource
將出如今其類路徑中包含該jar的任何應用程序中:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
若是要使用Spring Boot配置日誌設置,則應將此配置放在‘bootstrap.[yml | properties]
’,若是你但願它適用於全部事件。
要使Spring Cloud正確初始化日誌記錄配置,你不能使用自定義前綴,例如,初始化日誌記錄系統時,使用
custom.loggin.logpath
不被Spring Cloud識別。
應用程序偵聽EnvironmentChangeEvent
並以幾種標準方式對更改作出反應(用戶能夠正常方式將其餘ApplicationListener
添加爲@Beans
),當觀察到EnvironmentChangeEvent
時,它有一個已更改的鍵值列表,應用程序使用它們:
@ConfigurationProperties
beanlogging.level.*
中的任何屬性設置記錄器級別請注意,默認狀況下,Config Client不會輪詢Environment
中的更改,一般,咱們不建議使用這種方法來檢測更改(儘管你可使用@Scheduled
註解進行設置)。若是你有一個擴展的客戶端應用程序,最好將EnvironmentChangeEvent
廣播到全部實例,而不是讓它們輪詢更改(例如,經過使用Spring Cloud Bus)。
EnvironmentChangeEvent
涵蓋了一大類刷新用例,只要你能夠實際更改環境併發布事件便可,請注意,這些API是公共的,而且是核心Spring的一部分。你能夠經過訪問/configprops
端點(一個正常的Spring Boot Actuator功能)來驗證更改是否綁定到@ConfigurationProperties
bean。例如,DataSource
能夠在運行時更改其maxPoolSize
(Spring Boot建立的默認DataSource
是@ConfigurationProperties
bean)並動態增長容量。從新綁定@ConfigurationProperties
不包括另外一大類用例,這類用例你須要更多地控制刷新,而且須要對整個ApplicationContext
進行原子性更改,爲了解決這些問題,咱們有@RefreshScope
。
當配置發生變化時,標記爲@RefreshScope
的Spring @Bean
會獲得特殊處理,該特性解決了只有在初始化狀態bean時才注入配置的有狀態bean的問題。例如,若是DataSource
在經過Environment
更改數據庫URL時具備打開的鏈接,你可能但願這些鏈接的持有者可以完成他們正在作的事情,而後,下次從池中借用某個鏈接時,它會得到一個帶有新URL的鏈接。
有時,甚至可能必須在某些只能初始化一次的bean上應用@RefreshScope
註解,若是bean是「不可變的」,則必須使用@RefreshScope
註解bean,或者在屬性鍵spring.cloud.refresh.extra-refreshable
下指定classname
。
若是你本身建立一個DataSource
bean而且該實現是一個HikariDataSource
,則返回最具體的類型,在本例中爲HikariDataSource
,不然,你須要設置spring.cloud.refresh.extra-refreshable=javax.sql.DataSource
。
刷新做用域bean是在使用它們時初始化的惰性代理(即,在調用方法時),而且做用域充當初始化值的緩存,要強制bean在下一個方法調用上從新初始化,必須使其緩存條目無效。
RefreshScope
是上下文中的一個bean,它有一個公共refreshAll()
方法,經過清除目標緩存來刷新做用域中的全部bean,/refresh
端點公開此功能(經過HTTP或JMX),要按名稱刷新單個bean,還有一個refresh(String)
方法。
要公開/refresh
端點,你須要將如下配置添加到你的應用程序:
management: endpoints: web: exposure: include: refresh
@RefreshScope
(在技術上)在@Configuration
類上工做,但它可能會致使使人驚訝的行爲。例如,它並不意味着該類中定義的全部@Beans
自己都在@RefreshScope
中,具體來講,依賴於那些bean的任何東西都不能依賴於在啓動刷新時更新它們,除非它自己在@RefreshScope
中。在這種狀況下,它會在刷新時重建,並從新注入其依賴項,此時,它們將從刷新的@Configuration
從新初始化。
Spring Cloud有一個Environment
預處理器,用於在本地解密屬性值,它遵循與Config Server相同的規則,並經過encrypt.*
具備相同的外部配置。所以,你可使用{cipher}*
形式的加密值,只要有有效密鑰,它們就會在主應用程序上下文獲取Environment
設置以前被解密。要在應用程序中使用加密功能,你須要在類路徑中包含Spring Security RSA(Maven:"org.springframework.security:spring-security-rsa
"),而且你還須要JVM中的全強度JCE擴展。
若是因爲「Illegal key size」而致使異常,而且你使用Sun的JDK,則須要安裝Java加密擴展(JCE)無限制強度權限策略文件,有關更多信息,請參閱如下連接:
不管你使用哪一種版本的JRE/JDK x64/x86,都要將文件解壓縮到JDK/jre/lib/security
文件夾中。
對於Spring Boot Actuator應用程序,可使用一些其餘管理端點,你可使用:
POST
到/actuator/env
以更新Environment
並從新綁定@ConfigurationProperties
和日誌級別。/actuator/refresh
從新加載引導上下文並刷新@RefreshScope
bean。/actuator/restart
關閉ApplicationContext
並從新啓動它(默認狀況下禁用)。/actuator/pause
和/actuator/resume
用於調用Lifecycle
方法(ApplicationContext
上的stop()
和start()
)。若是禁用/actuator/restart
端點,則/actuator/pause
和/actuator/resume
端點也將被禁用,由於它們只是/actuator/restart
的特殊狀況。