spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

配置形式

spring-boot的配置包括:

  • 自動配置

  • 外化配置

外化配置通過將可變量分離出來,使得我們可以在不同的環境中使用同一份代碼。

外化配置表現形式不單單是 .properties 和 .yml 屬性文件,還可以使用環境變量和命令行參數等來實現。

由於有好多外部配置來源,所以需要解決配置衝突問題,解決方案是通過優先級,下面是屬性讀取順序:

spring-boot 配置從使用到原理

  1. 本地 Devtools 全局配置

  2. 測試時 @TestPropertySource 註解配置

  3. 測試時 @SpringBootTest 註解的 properties 配置

  4. 命令行配置

  5. SPRINGAPPLICATIONJSON 配置

  6. ServletConfig 初始化參數配置

  7. ServletContext 初始化參數配置

  8. Java 環境的 JNDI 參數配置

  9. Java 系統的屬性配置

  10. OS 環境變量配置

  11. 只能隨機屬性的 RandomValuePropertySource 配置

  12. 工程 jar 之外的多環境配置文件(application- {profile}.properties 或 YAML)

  13. 工程 jar 之內的多環境配置文件(application- {profile}.properties 或 YAML)

  14. 工程 jar 之外的應用配置文件(application.properties 或 YAML)

  15. 工程 jar 之內的應用配置文件(application.properties 或 YAML)

  16. @Configuration 類中的 @PropertySource 註解配置

  17. 默認屬性配置(SpringApplication.setDefaultProperties 指定)

配置使用方法

講了配置後,下一步就是介紹使用方法了:

  1. 通過@Value註解

  2. 通過@ConfigurationProperties綁定到配置類上

  3. 通過Environment獲取

先看第一個@Value註解

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

第二個@ConfigurationProperties註解

這個東西是個啥呢?看代碼:

spring-boot 配置從使用到原理

順著代碼註釋我們去看ConfigurationPropertiesBindingPostProcessorEnableConfigurationProperties

ConfigurationPropertiesBindingPostProcessor

我們先來看ConfigurationPropertiesBindingPostProcessor

spring-boot 配置從使用到原理

上面繼承圖中 ApplicationContextAware 是 Spring 提供的獲取 Spring 上下文中指定對象的方法,會在 BeanPostProcessor 之前調用,我們先來看 BeanPostProcessor。

BeanPostProcessor

BeanPostProcessor 接口定義了兩個方法:

  • postProcessBeforeInitialization:在 Bean 初始化回調前調用

  • postProcessAfterInitialization:在 Bean 初始化回調完成後進行調用,而且會在 afterPropertiesSet 方法回調之後。

所以我們只需要實現BeanPostProcessor接口,就能夠控制Bean初始化前後的操作。

下面我們來探究下到底是怎麼實現的,查看實現的原理的萬能方式是打斷點調試,來看下我們調用棧:

spring-boot 配置從使用到原理

我們先來看第一個方法:AbstractAutowireCapableBeanFactory.initializeBean

spring-boot 配置從使用到原理

上面我們列舉出了主要的方法,看名字大概就能知道功能,來看applyBeanPostProcessorsAfterInitialization

spring-boot 配置從使用到原理

看裡面的重點函數getBeanPostProcessors

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

InitializingBean 中 afterPropertiesSet 方法處打斷點。

spring-boot 配置從使用到原理

可以說是看到了老朋友,也是AbstractAutowireCapableBeanFactory.initializeBean方法,裡面的initializeBean方法如下:

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

EnableConfigurationProperties

還記得之前的圖:

spring-boot 配置從使用到原理

介紹完 ConfigurationPropertiesBindingPostProcessor 後,我們介紹 EnableConfigurationProperties。

spring-boot 配置從使用到原理

@Import 可以將對應的 Bean 導入到 Spring 上下文中。如果類在工程中的話那麼直接使用 @Configuration 註解即可,Spring 會自動識別的。但是如果在其他 jar 包或框架上,沒有配置到自動掃描的目錄中或者是沒有添加 @Configuration 註解,那麼就需要使用 @Import 將其導入到項目中來。

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

spring-boot 配置從使用到原理

到這裡我們來捋下整個思路:

  1. 我們的出發點是想看 為何加個註解 ConfigurationProperties 到類上,就能實現自動屬性注入了

  2. 我們去看了註解 ConfigurationProperties 的定義,註釋中讓我們去看 ConfigurationPropertiesBindingPostProcessor 和 EnableConfigurationProperties

  3. 我們先去看了 ConfigurationPropertiesBindingPostProcessor ,給出了類的繼承圖,上面需要關注的是 BeanPostProcessor 和 InitializingBean

  4. BeanPostProcessor 和 InitializingBean 一起給加載 Bean 的過程中流出了3個擴展點,調用的順序是:postProcessBeforeInitialization -> afterPropertiesSet -> postProcessAfterInitialization

  5. 在 postProcessBeforeInitialization 中完成了屬性的綁定

  6. 接著我們要去看 EnableConfigurationProperties 註解,發現裡面的@Import是加載需要的Bean進來

以上就是我們目前的一個解決問題的思路,下面我們來看 EnableConfigurationProperties 這個Enable**是在哪個地方引入到SpringBoot中的呢?

我們會發現在包org.springframework.boot.autoconfigure下的context.ConfigurationPropertiesAutoConfiguration

spring-boot 配置從使用到原理

至於 ConfigurationPropertiesAutoConfiguration 這個加載進來呢?

這就到了 Spring-boot的精髓 EnableAutoConfiguration 。

EnableAutoConfiguration

我們可以在包org.springframework.boot.autoconfigure中的spring.factories中定義了好多自動配置的類:

spring-boot 配置從使用到原理

所以我們就到了EnableAutoConfiguration

spring-boot 配置從使用到原理

接著我們就會到了@SpringBootApplication,裡面有註解 EnableAutoConfiguration

spring-boot 配置從使用到原理

我們下一步自然就進入@Import(AutoConfigurationImportSelector.class),裡面的 selectImports 將 Bean 加載進來:

spring-boot 配置從使用到原理

其中 DeferredImportSelector 的作用是在所有Bean處理完後最後再處理,特別適合Bean是根據條件Import進來的。

spring-boot 配置從使用到原理

挨行來看代碼,

spring-boot 配置從使用到原理

讀取了 META-INF/spring-autoconfigure-metadata.properties 配置文件,改配置文件中的內容如下:

spring-boot 配置從使用到原理

配置文件中配置了 SpringBoot 自動集成的各種 Enable 框架的執行條件,比如定義與其他 AutoConfiguration 框架的執行順序,需要哪些 Bean 在的時候才可以執行等。

spring-boot 配置從使用到原理

整個流程如下:

spring-boot 配置從使用到原理

圖片來自 第05課:@EnableAutoConfiguration 原理與實戰

EnableConfigurationPropertiesImportSelector

到這我們將介紹我們最後一部分,我們瞭解了 EnableConfigurationProperties 是如何開啟的了,下面就看其加載進入了哪些Bean進來。

spring-boot 配置從使用到原理

我們先不看代碼,先講下這個邏輯,我們有@SpringBootApplication,其開啟了@EnableAutoConfiguration,而 @EnableAutoConfiguration 會通過@Import去加載進 META-INF/spring-autoconfigure-metadata.properties 中定義的 autoconfigure 類來, 而其中就包含了 EnableConfigurationProperties,下面我們就看看 EnableConfigurationProperties 的 @Import 去將有相關 的Bean加載進來了,整個邏輯清晰後,我們就能來看 EnableConfigurationPropertiesImportSelector 了,具體方法還是打斷點,裡面會有兩個方法來註冊Bean。

spring-boot 配置從使用到原理

會將 EnableConfigurationProperties 中寫的Bean註冊進來,一個例子就是:

spring-boot 配置從使用到原理

上面會將JacksonProperties加載進來。

spring-boot 配置從使用到原理

這裡就將我們之前介紹的ConfigurationPropertiesBindingPostProcessor加載了進來。

總結

以上就是我們的整個spring-boot的配置原理解析,總結下整個思路:

  1. 我們的出發點是想看 為何加個註解 ConfigurationProperties 到類上,就能實現自動屬性注入了

  2. 我們去看了註解 ConfigurationProperties 的定義,註釋中讓我們去看 ConfigurationPropertiesBindingPostProcessor 和 EnableConfigurationProperties

  3. 我們先去看了 ConfigurationPropertiesBindingPostProcessor ,給出了類的繼承圖,上面需要關注的是 BeanPostProcessor 和 InitializingBean

  4. BeanPostProcessor 和 InitializingBean 一起給加載 Bean 的過程中流出了3個擴展點,調用的順序是:postProcessBeforeInitialization -> afterPropertiesSet -> postProcessAfterInitialization

  5. 在 postProcessBeforeInitialization 中完成了屬性的綁定

  6. 接著我們要去看 EnableConfigurationProperties 註解,發現裡面的@Import是加載需要的Bean進來

  7. EnableConfigurationProperties @Import 進來的Bean就包含了之前的 ConfigurationPropertiesBindingPostProcessor


分享到:


相關文章: