Spring實現原理分析(二十五).Spring Boot如何把application.*中的配置數據轉換成對象

       大家好!用過spring boot的人應該都知道“application.properties”和“application.yml”這兩個配置文件吧,最常見的就是在這兩個文件裏面配置數據庫連接信息。那麼,今天我要向大家揭祕,spring boot是何時加載它們,以及如何應用配置文件的過程。


一. 何時加載application.*

       spring boot的啓動是由SpringApplication負責的,其中有一個很重要的run(String... args)方法。在run方法中有一個步驟是預準備環境對象,即ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners, ApplicationArguments)方法。該方法會通知所有已註冊的事件監聽器(ApplicationListener),通知它們環境對象(Environment)已經創建了,可以爲它添加屬性源(PropertySource)了。對於Environment沒有概念的朋友,可以看我之前的博客

       配置文件事件監聽器(ConfigFileApplicationListener)收到這個通知後做出迴應,就把"application.properties"和"application.yml"中的內容轉換成屬性源添加到環境對象。那麼,配置文件事件監聽器又是從哪冒出來的呢?它被配置在autoconfigure's jar包裏的spring.factories文件中,很多跟boot相關的jar包裏都包含這個文件。在執行run(String... args)之前,spring就已把這個事件監聽器註冊到bean工廠(BeanFactory)。


二. 把application.*中的配置數據輸送到哪些對象呢?

      把配置數據輸送到被@ConfigurationProperties註解的類,這些類的類名往往是這樣的“xxxxxxProperties ”,比如“WebMvcProperties”。我看下WebMvcProperties類的定義。
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties 
{
     。。。省略
}

註解的prefix屬性值是"spring.mvc",這個意思就是把application.*中所有前綴是spring.mvc的配置數據綁定到WebMvcProperties的屬性,換句話說,就是WebMvcProperties持有所有關於spring mvc的配置。

       @ConfigurationProperties註解本身的功能我就不介紹了,大家可以百度下,支持鬆散命名,支持jsr303校驗。比如說,WebMvcProperties中某個屬性被jsr303校驗器註解了,那麼從application.*中把配置數據綁定到屬性前,會先對配置值執行校驗。可能大家又會有個疑問,是誰負責把application.*中的配置數據輸送到對象呢,這個行爲發生在什麼時候?


三. 誰負責把application.*中的配置數據輸送到對象,何時輸送。

      執行輸送任務的是ConfigurationPropertiesBindingPostProcessor(一個bean後處理器)在創建bean對象過程中的初始化bean步驟之前發生。那麼,ConfigurationPropertiesBindingPostProcessor又是被誰註冊到bean工廠的呢?答案是@EnableConfigurationProperties,我們看下這個註解的定義。

@Import(EnableConfigurationPropertiesImportSelector.class)
public @interface EnableConfigurationProperties 
{
	。。。省略
}
       這個註解本身又被@Import(EnableConfigurationPropertiesImportSelector.class)註解了,被導入的EnableConfigurationPropertiesImportSelector是一個導入選擇器,這個類的作用是導入“ConfigurationPropertiesBeanRegistrar.class”和“ConfigurationPropertiesBindingPostProcessorRegistrar.class”,被導入的這兩個類有一個共同的特點,它們都實現了ImportBeanDefinitionRegistrar接口,也就是說被導入的這兩個類本身的作用是往bean工廠註冊bean定義對象的。

ConfigurationPropertiesBindingPostProcessorRegistrar:負責註冊ConfigurationPropertiesBindingPostProcessor,這個bean後處理器的作用前面說了。

ConfigurationPropertiesBeanRegistrar : 負責註冊配置類依賴的被@ConfigurationProperties註解的類,比如DispatcherServletConfiguration依賴WebMvcProperties,於是乎WebMvcProperties也被註冊到bean工廠了。

      那麼,爲什麼會發生上述操作呢,答案是spring boot默認定義一些被@EnableConfigurationProperties註解的配置類,比如DispatcherServletConfiguration,我們看下它的定義。

@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration 
{
   。。。
}
     不知道讀者看到這裏是被饒暈了,還是有種恍然大悟的感覺呢!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章