springBoot自動配置原理分析及自定義starter

現在java項目基本都是springboot項目構建的,我們本着他們提出的約定大於配置的思想,使用起來都特別簡單,很多情況下我們主需要引入幾個start的jar包,寫幾個註解就能用,可是你們知道這裏面的原理嗎?那我們今天就來分析一下springBoot的自動配置原理和start的原理,順便再自己寫一個start來加深印象。

 

1.@Import是什麼

我們之前創建一個Bean可以使用@Configuration與@Bean這兩個註解配合使用來將原來配置在xml文件裏的bean通過java代碼的方式進行描述。

@Import註解提供了@Bean註解的功能,可以把一個Bean加入到IOC容器裏面,這次@Import的源碼分析我就不做了,後續的Spring源碼會有這裏面的講解的,這次我們就單純的看下這個註解是怎樣使用的吧。

2.@Import怎麼用

第一種用法:

語法:

@Import({ 類名.class , 類名.class... })
public class TestDemo {

}

代碼如下:

這個Import是沒有加上@Controller,Service等等任何註解的

我們看下IOC容器裏面有啥東西吧。

第二種用法:ImportSelector方式【重點】

這種方式的前提就是一個類要實現ImportSelector接口,假如我要用這種方法,目標對象是Myclass這個類,分析具體如下:

第三種用法:ImportBeanDefinitionRegistrar方式

同樣是一個接口,類似於第二種ImportSelector用法,相似度80%,只不過這種用法比較自定義化註冊,具體如下:

這個就是這三種用法,在SpringBoot裏面大量使用的哦。

我想說一點就是,我們可以看下我們第一種和第二種用法,輸出的beanDefinitionName是類的全路徑名,而第三種是類名的首字母小寫哦。

進入今天的主題之一:Springboot的自動配置原理

首選從一個註解:@SpringBootApplication看起:

既然是自動配置,我猜大家應該知道是哪一個類的作用吧?沒錯,就是@EnableAutoConfiguration

我看看這個註解,利用我們上面講的@Import知識,注入了一個AutoConfigurationImportSelector的Bean

我們可以詳細的分析一下字段源碼做的事情:

首先去loadMetadata,返回AutoConfigurationMetadata:

這從這個path下獲取到這些Metadata,這其實是spi機制,等下再介紹這個。

我們看下這個路徑下面都有神馬東西:

我們可以看到,這裏面只要是左面的key帶有ConditionaXXX的後面都有一個value值,我們知道ConditionaonXXX代表着條件注入,就是如果有這個條件,我們就注入對應的Bean。

在分析 AutoConfigurationImportSelector 的源碼時,會 先掃描 spring-autoconfiguration-metadata.properties 文件,最後在掃描 spring.factories 對應的類時,會結合 前面的元數據進行過濾,爲什麼要過濾呢? 原因是很多 的@Configuration 其實是依託於其他的框架來加載的, 如果當前的 classpath 環境下沒有相關聯的依賴,則意味 着這些類沒必要進行加載,所以,通過這種條件過濾可以 有效的減少@configuration 類的數量從而降低 SpringBoot 的啓動時間。

我們再來看下面的源碼:getAutoConfigurationEntry

分析:

首先把我們上一步獲取到的Metadata信息,變成AnnotationAttributes

主要看這個方法:getCandidateConfigurations

這裏面加載META-INF/spring.factories文件中尋找目前jar包中是否配置了相關支持自動配置的類的集合

這個spring.factories文件也是一組一組的key=value的形式,其中一個key是EnableAutoConfiguration類的全類名,而它的value是一個xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔,如下圖所示:

這個@EnableAutoConfiguration註解通過@SpringBootApplication被間接的標記在了Spring Boot的啓動類上。在SpringApplication.run(...)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類加載到Spring容器中。

然後做了一個Set去重,又做了一個我們主動排除的自動注入的類:

Set<String> exclusions = getExclusions(annotationMetadata, attributes);

最後在把這些類剔除掉,返回。

最後返回可以自動注入的那些IOC容器的Bean

這就是這個源碼的解析,爲了能夠讓大家能夠更明白一點,我打算寫一個案例來讓大家明白這個自動配置的原理東西。

我們創建一個新的spring項目,需要有spring的依賴,用spring的註解,裏面東西超級簡單。

我們在resources目錄下,創建一個spring.factories文件:

然後install這個項目,另外一個項目導入這個項目的pom地址。

我們就可以自動注入這個類了

啥都沒弄,就自動進入這個IOC容器裏面了,現在大家應該懂了吧。我們知道spring加載這些自動配置的類是先加載META-INF/spring-autoconfigure-metadata.properties文件裏面的配置的,我們同樣可以演示一波:

在新創建的那個項目裏面,加上這個配置:

加上這個代表啥意思?

就是想要依賴這個jar包,你需要在carry.CarryConfig下面有這個TestClass這個類。

我們install這個項目,另一個項目不做任何改動,我們看下會不會調用成功:

報錯了,在IOC容器裏面找不到這個bean,那咋辦呢?我們只需要在我們的項目裏面創建一個我們再另一個項目要求配置的類就可以了

哈哈,我這個案例雖然很簡單,但是對於幫助理解這個自動配置的源碼還是有很大的幫助,是不是呢?

我們下面來看下starter

Starter 是 Spring Boot 中的一個非常重要的概念,Starter相當於模塊,它能將模塊所需的依賴整合起來並對模塊內的 Bean 根據環境( 條件)進行自動配置。使用者只需要依賴相應功能的 Starter,無需做過多的配置和依賴,Spring
Boot 就能自動掃描並加載相應的模塊。我們在 Maven 的依賴中加入 spring-bootstarter-web 就能使項目支持 Spring MVC,並且 SpringBoot 還爲我們做了很多默認配置,無需再依賴 spring-web、spring-webmvc 等相關包及做相關配置就能夠立即使用起來存在很多開箱即用的 Starter 依賴,使得我們在開發業務代碼時能夠非常方便的、不需要過多關注框架
的配置,而只需要關注業務即可。

下面我們就來自定義一個starter來感受一下:

1創建一個項目:

2.pom文件

3.定義一個實體類映射的配置信息

@ConfigurationProperties(prefix = "carry.hello") 它可以把相同前綴的配置信息通過配置項名稱映射成實體類,比如我們這裏指定 prefix = "carry.hello" 這樣,我們就能將以carry.hello爲前綴的配置項拿到了。
ps:其實這個註解很強大,它不但能映射成String或基本類型的變量。還可以映射爲List,Map等數據結構。

4.定義一個service

5.定義一個配置類

這裏,我們將HelloService類定義爲一個Bean,交給Ioc容器。

▲  @Configuration 註解就不多說了。

▲  @EnableConfigurationProperties 註解。該註解是用來開啓對3步驟中 @ConfigurationProperties 註解配置Bean的支持。也就是@EnableConfigurationProperties註解告訴Spring Boot 能支持@ConfigurationProperties。

當然了,也可以在 @ConfigurationProperties 註解的類上添加 @Configuration 或者  @Component 註解

6.spring.factories文件:

讓這個能夠自動注入

7.install這個項目

8.在另外一個項目引入這個項目的pom地址

9.屬性設置:

這在yml文件是有提示的,這就是我們可以在yml配置端口啥的原因,以後你想看可以配置哪些屬性,就可以找ConfigurationProperties裏面配置了哪些屬性了

10.調用:

11.運行結果:

這就是一個簡單的自定義的starter,你們get到了嗎?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章