Spring Boot 解決方案 - 配置
習慣優於配置
Spring Boot 專案的重要思想就是“習慣優於配置”,這也是為什麼該專案誕生的原因,讓開發者免於 Spring 生態中各種專案的配置。儘管如此,但專案中完全零配置還是很難做到的,因此本篇文章就來講解一下 Spring Boot 中的配置。
分析預設專案
先從預設建立的專案開始分析,Spring Boot 預設建立的專案會有一個如下所示的入口類,該類被標註了@SpringBootApplication
註解,而該註解相當於@SpringConfiguration
、@EnableAutoConfiguration
和@ComponentScan
三個的結合,由於前兩個註解才和配置有關,所以下面只講解前兩個。
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
@EnableAutoConfiguration
若標記了@EnableAutoConfiguration
註解, Spring Boot 會根據 ClassPath 中的 Jar 包依賴來自動配置程式,例如添加了 Web 相關的依賴則會自動進行 Web 配置,且注意官方建議將該註解標記且只標記一次
在標有@Configuration
的類上。
由於自動配置是非侵入性的,因此可以自定義配置來覆蓋原有的自動配置,而且還可以禁止某些自動配置類,例如下面例子禁止了資料來源的自動配置。
@Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class DemoConf { // ... }
@SpringConfiguration
由原始碼可知@SpringConfiguration
是@Configuration
的別名,而被@Configuration
標註的類,相當於一個配置檔案可進行各種自定義配置,例如下面配置類中註冊了一個 Bean 。
@Configuration public class AppConf { @Bean public DemoBean demoBean() { return new DemoBean(); } }
屬性檔案及其優先順序
標註@Configuration
的配置類描述瞭如何進行配置類似於函式,而屬性檔案的屬性則相當於引數。
預設情況下配置類會按如下列表從高到低的優先順序
讀取屬性檔案,且預設讀取檔名為application.suffix
的屬性檔案,其中的suffix
為properties
或yml
其中之一,分別代表支援的兩種型別檔案。
./config ./config
注意優先順序高的屬性檔案中的相同屬性,會覆蓋掉優先順序低的檔案中的屬性配置,例如專案資源目錄下有如下檔案結構,根據上述規則最終獲取到的demo.name
的值就為foo
。這樣的設計可以方便利用外部屬性檔案改變程式某些配置屬性,例如改變繫結埠或者資料庫地址。
/resources |- /config |- application.properties<- demo.name=foo |- application.properties<- demo.name=bar
執行時指定屬性
除了可用外部屬性檔案覆蓋內部屬性檔案的屬性,還可以在執行程式時指定屬性,例如下面命令指定了demo.name
屬性值為foo
。
java -jar demo.jar --demo.name=foo
當然若是不想執行時指定屬性,也可使用SpringApplication.setAddCommandLineProperties(false)
來禁止讀取命令列的屬性。
指定屬性檔案
可利用@PropertySource
來指定屬性檔案,例如下面的例子,但注意只支援properties
和XML
兩種型別的屬性檔案。
@Configuration @PropertySource("classpath:/demo.properties") // or @PropertySource("file:/path/demo.xml") public class AppConf { // ... }
雖然不支援YAML
等其他型別的檔案,但可以自己實現PropertySourceFactory
介面(該特性在 Spring 4.3 中引入),然後如下面的例子在註解中用factory
指定實現類,具體實現參考這篇文章
。
@Configuration @PropertySource(value="classpath:/demo.yml", factory=YamlPropertySourceFactory.class) public class AppConf { // ... }
多環境的屬性檔案
對於不同環境,只需要建立名為application-env.sufix
的屬性檔案,其中env
和suffix
分別為環境名和字尾名,然後在預設的屬性檔案application.suffix
中配置屬性spring.profiles.active=env
即可。
例如建立如下的檔案目錄結構,然後在application.properties
檔案中配置屬性spring.profiles.active=dev
,就可以載入名為application-dev.properties
的屬性檔案。
/resources |- application.properties |- application-dev.properties |- application-prod.properties
使用屬性
使用@Value
加 EL 表示式就可以獲取屬性檔案中的屬性,例如下面一個簡單的例子。
/* application.properties 's content */ // demo.name=foo @Configuration public class AppConf { @Value("${demo.name}") private String name; }
@Value
註解不支援批量匯入屬性,但使用@ConfigurationProperties
就可以批量匯入屬性,例如下面的例子。
/* application.properties 's content */ // demo.name=foo // demo.addr=bar @Configuration(prefix = "demo") // same as @Configuration("demo") public class AppConf { private String name; private String addr; // getters and setters }
除了能批量匯入之外,其與@Value
還有其他區別,具體參考這篇文章。