SpringBoot 配置項解析 && @PropertySource 注解的處理


SpringBoot 的配置解析是通過 Environment 來實現的。

Environment:
與屬性相關的 Environment 對象的作用是為用戶提供一個方便的服務接口,用於配置屬性源並從中解析屬性。

Environment 本身實現了 PropertyResolver 接口,最終會委托給 PropertySourcesPropertyResolver 去解析配置。

org.springframework.core.env.PropertySourcesPropertyResolver.getProperty

 1 protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
 2     if (this.propertySources != null) {
 3         for (PropertySource<?> propertySource : this.propertySources) { // 1. 循環 PropertySources
 4             if (logger.isTraceEnabled()) {
 5                 logger.trace("Searching for key '" + key + "' in PropertySource '" +
 6                         propertySource.getName() + "'");
 7             }
 8             Object value = propertySource.getProperty(key); // 2. 從 PropertySource 中獲取 key 對應的配置
 9             if (value != null) {
10                 if (resolveNestedPlaceholders && value instanceof String) {
11                     value = resolveNestedPlaceholders((String) value); // 3. 解析占位符 ${}
12                 }
13                 logKeyFound(key, propertySource, value);
14                 return convertValueIfNecessary(value, targetValueType); // 4. 轉換成指定類型
15             }
16         }
17     }
18     if (logger.isTraceEnabled()) {
19         logger.trace("Could not find key '" + key + "' in any property source");
20     }
21     return null;
22 }

 

 

 最終獲取配置就是去各種 PropertySource 中去取 key 對應的配置值,SpringBoot 支持多種類型的 PropertySource 擴展:

RandomValuePropertySource -- 對 random.int, random.long, random.uuid 的支持
MapPropertySource -- 對 K,V 形式的配置支持
JsonPropertySource -- 對 Json 類型的配置支持
SystemEnvironmentPropertySource -- 對配置 key 中使用 .、下划線、中划線、大小寫的支持
CommandLinePropertySource -- 對啟動命令參數的支持
ServletContextPropertySource -- 對 ServletContext 的 initParam 的支持
JndiPropertySource -- 對 JNDI 類型的配置支持

 

@PropertySource 注解的處理

ConfigurationClassParser#doProcessConfigurationClass()
在處理 @PropertySource 時,會加載注解中定義的資源文件,然后添加到 Environment#propertySources 中。
添加時,如果指定了多個資源文件,則后面定義的會放到 propertySources 的前面。這個會影響配置優先級,即后定義的優先級高

// 對所有的 @PropertySource 而言的 // 單個 @PropertySource 中定義多個資源文件地址也受這個規則影響
if (this.propertySourceNames.isEmpty()) {
    propertySources.addLast(propertySource);
} else {
    String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
    propertySources.addBefore(firstProcessed, propertySource);
}

 注意:
這個規則是對所有的 @PropertySource 注解生效的,因為 ConfigurationClassParser 只有一個實例,所以 propertySourceNames 變量也是共用一個,所以它會對所有的 @PropertiesSource 注解生效。
從表現上來看就是:
1. 從全局來看,后加載的 @PropertySource 資源文件優先級會排在前面
2. 從局部來看,@PropertySource 中指定多個資源文件時,后定義的資源文件優先級更高

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM