頭禿了,Spring Boot 自動配置了解一波~
- 2020 年 11 月 20 日
- 筆記
- JAVA, springboot, 碼猿技術專欄
持續原創輸出,點擊上方藍字關注我

目錄
-
前言 -
源碼版本 -
@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進階」即可獲取,目錄如下:

