3.2.3 原理分析
3.2.3.1 源碼跟蹤
前面我們講解了在項目當中引入第三方依賴之后,如何加載第三方依賴中定義好的bean對象以及配置類,從而完成自動配置操作。那下面我們通過源碼跟蹤的形式來剖析下SpringBoot底層到底是如何完成自動配置的。
源碼跟蹤技巧:
在跟蹤框架源碼的時候,一定要抓住關鍵點,找到核心流程。一定不要從頭到尾一行代碼去看,一個方法的去研究,一定要找到關鍵流程,抓住關鍵點,先在宏觀上對整個流程或者整個原理有一個認識,有精力再去研究其中的細節。
要搞清楚SpringBoot的自動配置原理,要從SpringBoot啟動類上使用的核心注解@SpringBootApplication開始分析:
在@SpringBootApplication注解中包含了:
-
元注解(不再解釋)
-
@SpringBootConfiguration
-
@EnableAutoConfiguration
-
@ComponentScan
我們先來看第一個注解:@SpringBootConfiguration
@SpringBootConfiguration注解上使用了@Configuration,表明SpringBoot啟動類就是一個配置類。
@Indexed注解,是用來加速應用啟動的(不用關心)。
接下來再先看@ComponentScan注解:
@ComponentScan注解是用來進行組件掃描的,掃描啟動類所在的包及其子包下所有被@Component及其衍生注解聲明的類。
SpringBoot啟動類,之所以具備掃描包功能,就是因為包含了@ComponentScan注解。
最后我們來看看@EnableAutoConfiguration注解(自動配置核心注解):
使用@Import注解,導入了實現ImportSelector接口的實現類。
AutoConfigurationImportSelector類是ImportSelector接口的實現類。
AutoConfigurationImportSelector類中重寫了ImportSelector接口的selectImports()方法:
selectImports()方法底層調用getAutoConfigurationEntry()方法,獲取可自動配置的配置類信息集合
?
getAutoConfigurationEntry()方法通過調用getCandidateConfigurations(annotationMetadata, attributes)方法獲取在配置文件中配置的所有自動配置類的集合
?
getCandidateConfigurations方法的功能:
獲取所有基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件、META-INF/spring.factories文件中配置類的集合
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件和META-INF/spring.factories文件這兩個文件在哪里呢?
-
通常在引入的起步依賴中,都有包含以上兩個文件
-
在前面在給大家演示自動配置的時候,我們直接在測試類當中注入了一個叫gson的bean對象,進行JSON格式轉換。雖然我們沒有配置bean對象,但是我們是可以直接注入使用的。原因就是因為在自動配置類當中做了自動配置。到底是在哪個自動配置類當中做的自動配置呢?我們通過搜索來查詢一下。
在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports配置文件中指定了第三方依賴Gson的配置類:GsonAutoConfiguration
第三方依賴中提供的GsonAutoConfiguration類:
在GsonAutoConfiguration類上,添加了注解@AutoConfiguration,通過查看源碼,可以明確:GsonAutoConfiguration類是一個配置。
看到這里,大家就應該明白為什么可以完成自動配置了,原理就是在配置類中定義一個@Bean標識的方法,而Spring會自動調用配置類中使用@Bean標識的方法,并把方法的返回值注冊到IOC容器中。
自動配置源碼小結
自動配置原理源碼入口就是@SpringBootApplication注解,在這個注解中封裝了3個注解,分別是:
-
@SpringBootConfiguration
-
聲明當前類是一個配置類
-
-
@ComponentScan
-
進行組件掃描(SpringBoot中默認掃描的是啟動類所在的當前包及其子包)
-
-
@EnableAutoConfiguration
-
封裝了@Import注解(Import注解中指定了一個ImportSelector接口的實現類)
-
在實現類重寫的selectImports()方法,讀取當前項目下所有依賴jar包中META-INF/spring.factories、META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports兩個文件里面定義的配置類(配置類中定義了@Bean注解標識的方法)。
-
-
當SpringBoot程序啟動時,就會加載配置文件當中所定義的配置類,并將這些配置類信息(類的全限定名)封裝到String類型的數組中,最終通過@Import注解將這些配置類全部加載到Spring的IOC容器中,交給IOC容器管理。
最后呢給大家拋出一個問題:在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中定義的配置類非常多,而且每個配置類中又可以定義很多的bean,那這些bean都會注冊到Spring的IOC容器中嗎?
答案:并不是。 在聲明bean對象時,上面有加一個以@Conditional開頭的注解,這種注解的作用就是按照條件進行裝配,只有滿足條件之后,才會將bean注冊到Spring的IOC容器中(下面會詳細來講解)