1. 程式人生 > >頭禿了,Spring Boot 自動配置原始碼解析瞭解一波~

頭禿了,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 {}

上方標註了三個重要的註解,如下:

  1. @SpringBootConfiguration:其實就是@Configuration,因此主啟動類可以當做配置類使用,比如注入Bean等。
  2. @EnableAutoConfiguration:這個註解牛批了,名字就不一樣,開啟自動配置,哦,關鍵都在這了.....
  3. @ComponentScan:包掃描註解。

經過以上的分析,最終定位了一個註解@EnableAutoConfiguration,顧名思義,肯定和自動配置有關,要重點分析下。

@EnableAutoConfiguration幹了什麼?

想要知道做了什麼肯定需要看原始碼,如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

上方標註了兩個重要的註解,如下:

  1. @AutoConfigurationPackage:自動配置包註解,預設將主配置類(@SpringBootApplication)所在的包及其子包裡面的所有元件掃描到IOC容器中。
  2. @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()這個構造方法中,原始碼解析如下圖:

從上面原始碼分析可以知道,這裡掃描的包名是由兩部分組成,分別如下:

  1. @AutoConfigurationPackage註解中的兩個屬性解析得來的包名。
  2. 註解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進階」即可獲取,目錄如下: