江帥帥:精通 Spring Boot 系列 02

江帥帥:精通 Spring Boot 系列 02
1 @SpringBootApplication 註解
Spring Boot 的啓動類,也就是入口類,須要使用 @SpringBootApplication 註解來標註。在啓動類中,咱們的 main 方法就是 Java 應用程序的入口方法。spring

@SpringBootApplication 是一個組合註解,具體源碼以下:框架

江帥帥:精通 Spring Boot 系列 02

江帥帥:精通 Spring Boot 系列 02

其中,比較重要的三個註解是:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan。ide

2 @SpringBootConfiguration 註解spring-boot

主要是負責 Spring Boot 應用配置相關的註解,它也是組合註解,具體源碼以下:post

江帥帥:精通 Spring Boot 系列 02

經過源碼,能夠看到它也使用了 @Configuration 註解,它們兩個都是將當前類標註爲配置類,能將類中使用 @Bean 註解標記的方法對應的實例注入到 Spring 容器中,那實例名就是方法名。3d

另外在 @Configuration 註解源碼中,還看到有一個 @Component 註解,作了再次封裝,主要是把普通 POJO 實例化到 Spring 容器中。具體源碼以下:
江帥帥:精通 Spring Boot 系列 02對象

因此,更推薦你們在 Spring Boot 應用中使用 @SpringBootConfiguration。blog

3 @EnableAutoConfiguration 註解接口

主要用來啓動自動配置,Spring Boot 就可以根據依賴信息自動實現應用的相關配置,整體分爲兩個部分:一是收集全部 spring.factories 中EnableAutoConfiguration 相關 bean 的類,二是將獲得的類註冊到 Spring 容器中。將符合的配置都加載到 IoC 容器中。具體源碼以下:get

江帥帥:精通 Spring Boot 系列 02

組件調用關係圖,具體以下:

江帥帥:精通 Spring Boot 系列 02

這張圖,怎麼去理解呢?實際上是這樣的,涉及到了 BeanFactory 的建立。Spring 框架中會調用 ApplicationContext 的 refresh 方法來啓動 Spring 容器,而後就會建立 BeanFactory,接着掃描各類包,讀取使用到了 @Configuration、@Import、@SpringBootApplication 等註解標註的類,而後生成 BeanDefinition 最終註冊到 BeanFactory 中。

而後就交給 BeanFactoryPostProcessor 來執行,BeanFactory 後置處理器會處理 BeanDefinition,好比在 BeanFactoryPostProcessor 接口中,提供了 postProcessBeanFactory 方法來接收 ConfigurableListableBeanFactory 對象來處理。具體源碼以下:
江帥帥:精通 Spring Boot 系列 02

其餘相似 @Configuration 等配置性質的註解,就讓 ConfigurationClassPostProcessor 來處理。

上面的 ConfigurationClassPostProcessor 主要是 BeanFactoryPostProcessor 接口的實現類,主要是想從 BeanFactory 中獲取全部 BeanDefinition 列表,遍歷出那些使用了 @Configuration、@Import 等配置性質註解標註的類所對應的 BeanDefintion,而後進行註冊。具體源碼以下:
江帥帥:精通 Spring Boot 系列 02
江帥帥:精通 Spring Boot 系列 02

具體,咱們還能夠去看看它的 parse 方法是如何處理的,它會去解析註解。

江帥帥:精通 Spring Boot 系列 02

看到最後的 deferredImportSelectorHandler,這個內部類的裏面有一個 deferredImportSelectors 集合,主要是用來添加 AutoConfigurationImportSelector。這個內部私有類,主要維護了一個類型爲DeferredImportSelectorHolder 的 deferredImportSelectors 列表。這最後一句代碼,就是處理完其餘BeanDefinitions 後調用 process 方法。

再接着來看 process 方法,它負責自動配置類導入的內部實現,具體源碼以下:

江帥帥:精通 Spring Boot 系列 02

這個方法,須要這麼來理解:

首先,DeferredImportSelector 它會去從 spring-boot-autoconfigure 包路徑下的 META-INF/spring.factories 文件中找到 EnableAutoConfiguration 做爲 key,而後獲取對應的自動配置類列表。

第二步,在裏面經過 key 便可找到對應須要自動配置的類。接着會進行遍歷全部類名,加載和導入對應的配置類。

大體的思路是會先建立一個 ConfigurationClass 的對象,它會包含當前這個配置類,而後傳進被調用的 doProcessConfigurationClass 方法中,而後處理該類包含的註解。若是是 @Import 註解,則會放在 processImports 方法中進行處理。

再具體講,就是那些非 ImportSelector 接口實現類和ImportBeanDefinitionRegistrar 接口實現類的配置類,就會調用processConfigurationClass 方法來處理該自動配置類上面的其餘註解,並將該自動配置類內部使用了 @Bean 註解的全部方法,條件化生成 bean 並註冊到 Spring 容器,那最終就能夠提供特定功能組件的默認實現,也就實現了 SpringBoot 的自動配置功能,在你使用的時候,好比直接經過 @Autowried 註解就能夠注入某個功能組件,而不須要顯示配置。

具體源碼以下(這裏不貼所有源碼了,你們能夠看看它給出的註釋就明白了):

江帥帥:精通 Spring Boot 系列 02

4 獲取 Bean 類信息
咱們能夠來研究下這個註解,瞭解它是如何加載配置的。在源碼中,能夠看到 @Import({AutoConfigurationImportSelector.class}) 註解,導入的就是自動配置選擇器。

AutoConfigurationImportSelector 選擇器是 DeferredImportSelector 接口的實現類,會在 BeanFactory 中對全部 BeanDefinition 處理後執行來進行 SpringBoot 自動配置類的加載、導入操做等,並基於 @Conditional 條件化配置來決定是否將該配置類內部定義的 Bean 註冊到 Spring 容器。具體源碼以下:

江帥帥:精通 Spring Boot 系列 02

在 AutoConfigurationImportSelector.class 中,能夠看到實現了一個 selectImports 方法,用來導出 Configuration。方法中調用了 getAutoConfigurationEntry 方法,獲取 bean 類信息。具體源碼以下:

江帥帥:精通 Spring Boot 系列 02

繼續來看 getAutoConfigurationEntry 方法,具體源碼以下:

江帥帥:精通 Spring Boot 系列 02

再接着來看調用的 getCandidateConfigurations 方法,它主要是想獲取全部對應的配置,它裏面調用了 loadFactoryNames 方法,目的是要想加載 spring.factories 文件。它們的源碼具體以下:
江帥帥:精通 Spring Boot 系列 02

loadFactoryNames 方法的具體源碼以下:
江帥帥:精通 Spring Boot 系列 02

接着就在 loadSpringFactories 方法中,找到全部的 spring.factories 配置信息,而後所有返回。具體源碼以下:
江帥帥:精通 Spring Boot 系列 02

相關文章
相關標籤/搜索