頭禿了,Spring Boot 自動配置原始碼解析瞭解一波~
持續原創輸出,點選上方藍字關注我
目錄
前言 原始碼版本 @SpringBootApplication
幹了什麼?@EnableAutoConfiguration
幹了什麼?總結
前言
為什麼Spring Boot
這麼火?因為便捷,開箱即用,但是你思考過為什麼會這麼便捷嗎?傳統的SSM架構配置檔案至少要寫半天,而使用Spring Boot
之後只需要引入一個starter
之後就能直接使用,why???
原因很簡單,每個starter
內部做了工作,比如Mybatis
的啟動器預設內建了可用的SqlSessionFactory
。
至於如何內建的?Spring Boot
又是如何使其生效的?這篇文章就從原始碼角度介紹一下Spring Boot
原始碼版本
作者Spring Boot
是基於2.4.0
。每個版本有些變化,讀者儘量和我保持一致,以防原始碼有些出入。
@SpringBootApplication幹了什麼?
這麼說吧,這個註解什麼也沒做,廢物,活都交給屬下做了,原始碼如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}
上方標註了三個重要的註解,如下:
@SpringBootConfiguration
:其實就是@Configuration
,因此主啟動類可以當做配置類使用,比如注入Bean
等。@EnableAutoConfiguration
:這個註解牛批了,名字就不一樣,開啟自動配置,哦,關鍵都在這了.....@ComponentScan
:包掃描註解。
經過以上的分析,最終定位了一個註解@EnableAutoConfiguration
,顧名思義,肯定和自動配置有關,要重點分析下。
@EnableAutoConfiguration幹了什麼?
想要知道做了什麼肯定需要看原始碼,如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
上方標註了兩個重要的註解,如下:
@AutoConfigurationPackage
:自動配置包註解,預設將主配置類(@SpringBootApplication
)所在的包及其子包裡面的所有元件掃描到IOC容器
中。@Import
:該註解不必多說了,前面文章說過很多次了,這裡是匯入了AutoConfigurationImportSelector
,用來注入自動配置類。
以上只是簡單的分析了兩個註解,下面將會從原始碼詳細的介紹一下。
@AutoConfigurationPackage
這個註解幹了什麼?這個需要看下原始碼,如下;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
重要的還是@Import
註解,匯入了AutoConfigurationPackages.Registrar
,這個類是幹什麼的?原始碼如下圖:
其實就兩個方法,但是的最重要的就是registerBeanDefinitions
方法,但是這個方法不用看,肯定是注入Bean
,這裡的重點是注入哪些Bean
,重點原始碼如下:
//獲取掃描的包
new PackageImports(metadata).getPackageNames().toArray(new String[0])
跟進程式碼,主要邏輯都在#PackageImports.PackageImports()
這個構造方法中,原始碼解析如下圖:
從上面原始碼分析可以知道,這裡掃描的包名是由兩部分組成,分別如下:
從 @AutoConfigurationPackage
註解中的兩個屬性解析得來的包名。註解 AutoConfigurationPackage
所在的包名,即是@SpringBootApplication
所在的包名。
@AutoConfigurationPackage
預設將主配置類(@SpringBootApplication
)所在的包及其子包裡面的所有元件掃描到IOC容器中。
@Import(AutoConfigurationImportSelector.class)
這個註解不用多說了,最重要的就是AutoConfigurationImportSelector
,我們來看看它的繼承關係,如下圖:
這個類的繼承關係還是挺簡單的,實現了Spring
中的xxAware
注入一些必要的元件,但是最值得關心的是實現了一個DeferredImportSelector
這個介面,這個介面擴充套件了ImportSelector
,也改變了其執行的方式,這個在後面章節會介紹。
「注意」:這個類會導致一個誤區,平時看到
xxxSelector
已經有了反射弧了,肯定會在selectImports()
方法上DEBUG
,但是這個類壓根就沒執行該方法,我第一次看也有點懷疑人生了,原來它走的是DeferredImportSelector
的介面方法。
其實該類真正實現邏輯的方法是process()
方法,但是主要載入自動配置類的任務交給了getAutoConfigurationEntry()
方法,具體的邏輯如下圖:
上圖的邏輯很簡單,先從spring.factories
檔案中獲取自動配置類,在去掉@SpringBootApplication
中定義排除的自動配置類。
上圖中的第④
步就是從META-INF/spring.factories
中載入自動配置類,程式碼很簡單,在上一篇分析啟動流程的時候也有很多元件是從spring.facotries
檔案中載入的,程式碼都類似。
在springboot-autoconfigure
中的spring.facotries
檔案內建了很多自動配置類,如下:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
................
瞭解了
Spring Boot
如何載入自動配置類,那麼自定義一個自動配置類也是很簡單了,後續章節教你如何定製自己的自動配置類,裡面還是有很多門道的.....
總結
本文從原始碼角度分析了Spring Boot
的自動配置是如何載入的,其實分析起來很簡單,希望作者的這篇文章能幫助你更深層次的瞭解Spring Boot
。
另外作者的第一本PDF
書籍已經整理好了,由淺入深的詳細介紹了Mybatis基礎以及底層原始碼,有需要的朋友公號回覆關鍵詞「Mybatis進階」即可獲取,目錄如下: