前言
為什么Spring Boot
這么火?因為便捷,開箱即用,但是你思考過為什么會這么便捷嗎?傳統的SSM架構配置文件至少要寫半天,而使用Spring Boot
之后只需要引入一個starter
之后就能直接使用,why???
原因很簡單,每個starter
內部做了工作,比如Mybatis
的啟動器默認內置了可用的SqlSessionFactory
。
至於如何內置的?Spring Boot
又是如何使其生效的?這篇文章就從源碼角度介紹一下Spring Boot
的自動配置原理。
源碼版本
作者Spring Boot
是基於2.4.0
。每個版本有些變化,讀者盡量和我保持一致,以防源碼有些出入。
@SpringBootApplication干了什么?
這么說吧,這個注解什么也沒做,廢物,活都交給屬下做了,源碼如下:

上方標注了三個重要的注解,如下:
@SpringBootConfiguration
:其實就是@Configuration
,因此主啟動類可以當做配置類使用,比如注入Bean
等。@EnableAutoConfiguration
:這個注解牛批了,名字就不一樣,開啟自動配置,哦,關鍵都在這了.....@ComponentScan
:包掃描注解。
經過以上的分析,最終定位了一個注解@EnableAutoConfiguration
,顧名思義,肯定和自動配置有關,要重點分析下。
@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
如何加載自動配置類,那么自定義一個自動配置類也是很簡單了,后續章節教你如何定制自己的自動配置類,里面還是有很多門道的.....