本文來自網易雲社區
大部分比薩店也提供某種形式的自動配置。你可以點葷比薩、素比薩、香辣意大利比薩,或者是自動配置比薩中的極品——至尊比薩。在下單時,你並沒有指定具體的輔料,你所點的比薩種類決定了所用的輔料。但如果你想要至尊比薩上的全部輔料,還想要加墨西哥胡椒,又不想放蘑菇該怎么辦?你偏愛辣食又不喜歡吃菌類,自動配置不適合你的口味,你就只能自己配置比薩了嗎?當然不是,大部分比薩店會讓你以菜單上已有的選項為基礎進行定制。
外化屬性
屬性源
為了使應用能適應不同的環境,SpringBoot支持外化配置。可以使用.properties文件、YAML文件、環境變量、命令行參數等方式。
SpringBoot能從多種屬性源獲得屬性,包括以下幾處:
命令行參數
JVM系統屬性
操作系統環境變量
隨機生成的帶random.*前綴的屬性(在設置其他屬性時,可以引用它們,比如${random.long})
應用程序以外的application.properties或者application.yml文件
打包在應用程序內的application.properites或者application.yml文件
通過@propertySource標注的屬性源
默認屬性
優先級由高到低,即在上面的列表中“命令行參數”的優先級最高,會覆蓋下面其他屬性源的相同配置。
這里只挑選了部分比較常見的屬性源,詳細信息可以參考官網教程:24. Externalized Configuration
默認情況下SpringApplication將任何可選的命令行參數(以'--'開頭,比如,--server.port=9000)轉化為property,並將其添加到Spring Environment中。如上所述,命令行屬性總是優先於其他屬性源。
如果不想用這個特性可以用SpringApplication.setAddCommandLineProperties(false)來禁用。
YAML
SpringBoot支持YAML格式的配置文件文件后綴為yml,是一種更易讀寫的通用的數據串行化格式。
在SpringBoot中.yml效果相當於.properties,通常情況下二者是可以互相替換的,比如下面2種配置文件在SpringBoot中是等效的:
application.properties
server.port=8020 server.address=127.0.0.1
application.yml
server: port: 8020 address: 127.0.0.1
.yml文件在配置數據的時候具有面向對象的特性,更易閱讀。
雖然.yml配置和.properties基本等效,但也有略微區別,.yml配置不能用@propertySource注解加載。
Application屬性文件
SpringBoot會從以下位置加載.properties或.yml配置文件:
當前目錄下的/config目錄
當前目錄
classpath下的/config目錄
classpath的根目錄
優先級也是從高到低,高優先級的配置文件會覆蓋低優先級的配置。
使用.properties或.yml配置文件可以對SpringBoot的自動配置進行覆蓋,比如在默認的情況下http端口為8080,我們可以像上面的例子那樣在修改為8020。
SpringBoot提供了上百個這樣可以覆蓋的配置,具體可以查閱官網或者查看autoconfiguration包的的META-INF/spring-configuration-metadata.json和META-INF/additional-spring-configuration-metadata.json文件(這2個文件用來給IDE做輸入提示用,有一些簡單的描述)。
類型安全的配置屬性
有時候使用@Value("#{property}")注解注入配置會比較笨重,SpringBoot提供一個類型安全的方案,用強類型的Bean對象來替代屬性。
@ConfigurationProperties用法如下
@ConfigurationProperties(prefix = "acme")public class AcmeProperties { private boolean enabled; private final Security security = new Security(); // 省略getter、setter public static class Security { private String username; private String password; private List<String> roles = new ArrayList<>(Collections.singleton("USER")); // 省略getter、setter } }
@ConfigurationProperties的參數prefix表示前綴,AcmeProperties里的每個屬性的名稱便是具體的配置名。比如成員變量enabled綁定屬性acme.enabled。
上面這個例子表示AcmeProperties對象分別綁定下列屬性:
acme.ebalbe:布爾類型
acme.security.username:String類型
acme.security.pasword:String類型
acme.security.roles:類型是一個String集合
綁定配置之后還需要注冊Spring上下文中,有3種方式:
在java配置類中用@EnableConfigurationProperties注解激活
@Configuration@EnableConfigurationProperties(AcmeProperties.class)public class MyConfiguration { }
直接在AcmeProperties加@Component注解
@Component@ConfigurationProperties(prefix="acme")public class AcmeProperties { // ... see the preceding example}
在配置類中與@Bean注解組合
@Beanpublic AnotherComponent anotherComponent() { ... }
注冊之后,可以在任意地方使用@Autowire注解注入使用。
松散的綁定(Relaxed binding)
Spring Boot使用一些寬松的規則用於綁定Environment屬性到@ConfigurationProperties beans,所以Environment屬性名和bean屬性名不需要精確匹配。常見的有虛線匹配大寫(比如,context-path綁定到contextPath)和將環境屬性轉為大寫字母(比如,PORT綁定port)。
比如:
@ConfigurationProperties(prefix="acme.my-project.person")public class OwnerProperties { private String firstName; // 省略getter、setter}
可以綁定到:
Property | Note |
---|---|
acme.my-project.person.firstName | 標准的駝峰式命名 |
acme.my-project.person.first-name |
虛線表示,適用於.properties和.yml |
acme.my-project.person.first_name |
下划線表示,適用於.properties和.yml |
ACME_MYPROJECT_PERSON_FIRSTNAME |
大寫形式,適用於環境變量 |
@ConfigurationProperties vs @Value
Feature | @ConfigurationProperties |
@Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
SpEL evaluation |
No | Yes |
其他
查看當前生效的配置
SpringBoot默認提供了大量的自動配置,我們可以通過啟動時添加--debug參數來查看當前的配置信息。
激活的配置如下:
Positive matches:----------------- CodecsAutoConfiguration matched: - @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) CodecsAutoConfiguration.JacksonCodecConfiguration matched: - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)...
未激活的配置如下:
Negative matches:----------------- ActiveMQAutoConfiguration: Did not match: - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition) AopAutoConfiguration: Did not match: - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice', 'org.aspectj.weaver.AnnotatedElement' (OnClassCondition) ...
可以清楚的看到每個配置的條件,未激活的配置可以從這里直觀的看到原因。
debug可以用-Ddebug或--debug來啟用,也可以在.properties或.yml文件中配置debug的值為true。
去除指定的自動配置
用@EnableAutoConfiguration注解的exclude參數去除指定的自動配置:
import org.springframework.boot.autoconfigure.*;import org.springframework.boot.autoconfigure.jdbc.*;import org.springframework.context.annotation.*;@Configuration@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})public class MyConfiguration { }
小結
本節介紹了SpringBoot自定義配置的幾種方式。通過屬性外化,我們可以靈活選擇不同的屬性元來應對不同的場景。利用YAML可以讓配置文件結構化更易於閱讀,特別是有多層結構的屬性。@ConfigurationProperties提供類型安全的屬性使用方式,使用起來更加直觀。組合使用YAML和@ConfigurationProperties相信能讓項目的配置變得更加清晰。
SpringBoot不僅僅是幫助我們快速搭建一個可用的項目,在使用便利性上也提供了更多的姿勢。
網易雲新用戶大禮包:https://www.163yun.com/gift
本文來自網易實踐者社區,經作者金港生授權發布。