文章目錄
- 一、前言
- 二、Springboot四個特性
- 三、Springboot自動裝配
- 3.1 Springboot牛刀小試:整合redis,引入自動裝配
- 3.2 自動裝配的思考
- 3.3 自動裝配的模擬
- 3.3.1 兩個bean和兩個配置類
- 3.3.2 MyImportSelector類
- 3.3.3 @MyEnableConfiguration註解
- 3.3.4 詳細運行流程解釋
- 3.3.5 附加:既可以是配置類,也可以直接是bean類
- 3.4 從模擬到實際,解析自動裝配的底層原理
- 3.5 springboot自動裝配小結
- 3.6 SPI 設計思想
- 四、Springboot自動裝配進一步深入
- 4.1 Starter組件的原理:官方包依賴的條件觸發
- 4.2 demo spring.factories自定義組件的配置類的裝載
- 4.3 demo @ConditionalOnClass等註解實現條件配置
- 4.4 demo spring-autoconfigure-metadata.properties 實現條件配置
- 4.5 兩種配置方式一起使用
- 五、小結
一、前言
二、Springboot四個特性
springboot和微服務的關係是什麼?
回答:所有的微服務組件,都是集成到springboot上面,spring cloud也是一樣,在使用springcloud的時候,它應該和springboot在版本上兼容。
1、第一特性,EnableAutoConfiguration ,譯爲自動裝配。
2、第二特性,Starter啓動依賴,依賴於自動裝配的請求。
3、第三特性,Actuator監控,提供一些endpoint,這些endpoint可以基於http jmx 等形式去進行訪問health信息,metrics信息。
4、第四特性,Spring Boot CLI,它是爲springcloud提供的springboot命令行操作的功能,它通過groovy腳本快速構建springboot的應用,用得很少,一般還是基於idea應用構建springboot應用,略過。
小結:自動裝配和啓動依賴是不同的,兩者關係是啓動依賴依賴於自動裝配,監控提供一些訪問形式。
三、Springboot自動裝配
3.1 Springboot牛刀小試:整合redis,引入自動裝配
問題:能夠實現@Autowired依賴注入的前提是是IOC中存在這個bean的實例,那麼是誰裝載了這個bean實例?
回答:spring中裝載bean實例包括三種方式:xml文件 configuration類 enable註解,現在這三種方式我們都沒做,但是爲什麼springboot可以實現bean裝配,這就是springboot的自動裝配,完成bean的自動裝載,只要寫出來@Autowired,自動裝配的原理是怎麼實現的。
3.2 自動裝配的思考
3.2.1 自動裝配的思考
springboot爲什麼能夠完成自動裝配?
一句話總結,在pom.xml中引入的依賴(即jar包),都被約定好帶有統一的格式,都有XxxConfiguration類,使用時springboot直接對其掃描,就完成了裝配,但是這是對開發程序員不可見的,所以被稱爲自動裝配。每個第三方的starter裏面都有一個配置類XxxConfiguration類,這是一種約定。
Springboot自動裝載問題1:Spring引擎怎麼知道第三方組件starter裏面具體配置類在哪裏?
Springboot自動裝載問題2:如何實現批量掃描配置類XxxConfiguration redis mybatis dubble?
3.2.2 從靜態裝配bean實例到動態裝配bean實例
spring靜態裝配三種方式:xml文件 Configuration配置類 @Enable模塊裝配
spring動態裝配兩種方式:ImportSelector接口 Registator接口
每一個第三方starter裏面都有一個配置類XxxConfiguration,Springboot中使用多個第三方組件,如何批量掃描多個配置類XxxConfiguration
答案:批量bean加載機制。spring存在兩種動態bean裝載機制,一種是ImportSelector接口,一種是Registator接口,都是接口,本文介紹ImportSelector接口。
動態裝載:根據運行時上下文的具體運行條件來狀態來裝載配置類XxxConfiguration,不同於@Conditional。
3.3 自動裝配的模擬
這部分給出一個項目,模擬springboot自動裝配,項目結構如下:
3.3.1 兩個bean和兩個配置類
給出一個mybatis bean類、mybatis 模擬配置類、redis bean類、redis 模擬配置類
3.3.2 MyImportSelector類
模擬ImportSelector實現類,實現ImportSelector接口,返回配置類
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 在這裏去加載所有的配置類
// 通過某種機制去完成指定路徑的配置類的掃描就行?
// spring只需要知道 package.class.classname 就行了。
return new String[]{MybatisConfiguration.class.getName(), RedisConfiguration.class.getName()};
}
}
3.3.3 @MyEnableConfiguration註解
如何讓SpringbootApplication知道MyImportSelector返回的配置類?只需要聲明一個註解就可以完成。
定義一個註解,@Import(ImportSelector接口實現類.class)
SpringApplicationdemoApplication類中使用這個註解
3.3.4 詳細運行流程解釋
本項目中,其實SpringbootApplication不要使用@MyEnableConfiguration也可以,因爲SpringbootdemopageApplication所在包爲package com.example.demo;但是,兩個bean所在包爲package com.example.demo.mybatis 和 package com.example.demo.redis,這樣,啓動SpringbootdemopageApplication,會掃描所在包及其子包,就掃描到了兩個bean。
如果SpringbootdemopageApplication在com.example.demo.springbootdemo,必須配置@MyEnableConfiguration註解,啓動的時候,掃描@MyEnableConfiguration註解,然後知道它@Import(MyImportSelector.class),在MyImportSelector.class中,spring才知道兩個配置類的路徑,纔有了下面的裝載bean並打印出來。
3.3.5 附加:既可以是配置類,也可以直接是bean類
貌似MyImportSelector 返回值中直接放bean類會出現重複裝配的情況,總之,最好放配置類。
小結:這個實例告訴我們,springboot底層使用ImportSelector接口+註解動態裝載,無論第三方組件(項目中com.example.demo.mybatis 和 com.example.demo.redis模擬第三方組件,每一個組件都包括配置類和實體bean)的配置在哪裏,都可以用ImportSelector接口找到,並用註解告訴springboot,解決了第一個問題。對於n個配置類(項目中mybatis和redis模擬兩個配置類),可以批量配置,不是問題。
注意1:使用@ComponentScan或base-package不可以,它是靜態裝配,需要把掃描的路徑寫死,但是在使用一個第三方組件的時候,你是不知道它的bean或配置類在哪裏的,這就是靜態裝配的侷限,只能用動態裝配。
注意2:使用@Contional 也不僅,僅僅只是一個給出一個判斷,裝配還是不裝配,當然下文我們的有條件配置。
3.4 從模擬到實際,解析自動裝配的底層原理
3.4.1 從模擬到實際,springboot底層實現動態裝配
**可以看到,springboot的動態裝載的底層實現的@SpringBootApplication註解和我們的模擬的時候的自定義註解@MyEnableConfiguration底層是一樣的,都是集成ImportSelector接口實現其selectImports返回配置類數組。**難怪剛剛開始的redisTemplate可以自動裝配。
3.4.2 從模擬到實際,redis配置類
3.4.3 Springboot自動裝載的核心源碼
@Autowird
private RedisTemplate redisTemplate; // 自動裝載
第一,AutoConfigurationImportSelector 自動配置ImportSelector :getAutoConfigurationEntry 獲得自動配置/自動裝載實體
第二,SpringFactoriesLoader 表示 :spring.factories 加載
3.5 springboot自動裝配小結
開發程序員使用的時候,只要直接使用
@Autowired
private RedisTemplate<string,string> redisTemplate; // 自動配置好了的,直接用就好
問題:剛纔的項目只是在自己的項目中模擬,那麼具體實踐中,spring引擎怎麼知道具體starter配置類在哪裏?
回答:第一,所有starter遵循統一的約定,所有的starter組件,都需要一個META-INF/spring.factories文件,如下:
第二,springboot直接掃描配置文件(org.redis.RedisConfiguration org.mybatis.MybatisConfiguration)就好了,如下圖:
第三,自動裝載就完成了。
3.6 SPI 設計思想
3.6.1 什麼是SPI?
SPI 全稱 Service provider interface ,服務提供接口,這裏以各個不同的數據庫驅動爲例,如圖:
SPI 就是我們提供接口,接口的具體實現由第三方來做(這裏,不同的數據庫驅動是不同的,由數據庫廠商來完成),Java程序只要導入不同的jar包就可以執行,這就是SPI的擴展,就是服務提供接口的擴展。
爲什麼說spring.factories也是SPI,spring.factories 是基於key-value鍵值對的,其中key就是同一個Configuration,value由第三方具體實現;因爲每一個starter組件的jar包都有一個Configuration註解,提供一個與springboot溝通接口,其內部具體實現由第三方來做(redis mybatis dubbo),springboot只要導入不同的jar包(redis依賴 mybatis依賴 dubbo依賴)就好。
一句話總結DPI:
DPI 本身包含默認實現,但是也提供擴展點,需要的話可以替換,提高伸縮性和靈活性。
3.6.2 DPI設計思想的demo
DPI設計得以實現需要滿足以下條件:
1、需要在classpath目錄下創建一個META-INF/services
2、在該目錄下創建一個擴展點的全路徑名
2.1 文件中填充這個擴展點的實現
2.2 文件編碼格式UTF-8
3、ServiceLoader去進行加載
注意事項:META-INF和services目錄必須分開創建
maven quickstart 項目,maven clean maven install 之後變成jar包;
maven webapp 項目,maven clean maven install 之後變爲war包。
四、Springboot自動裝配進一步深入
starter組件與自動裝配緊密相連,因爲所有的第三方的starter組件都是遵循自動裝配的約定,提供spring.factories文件,提供配置類給springboot掃描完成自動裝配。
4.1 Starter組件的原理:官方包依賴的條件觸發
4.1.1 條件註解引入
4.1.2 官方依賴包中不存在spring.factories
對於官方的springboot starter,不存在spring.factories,那麼爲什麼不存在spring.factories,它又是如何加載的?
原來,starter包包括兩種,
官方包 spring-boot-starter-xxx 不存在 spring.factories 如spring-boot-starter-data-redis spring-boot-starter-thymeleaf
第三方包 xxx-spring-boot-starter 一定存在spring.factories
以Redis爲例,其配置類RedisAutoConfiguration不存在 spring-boot-starter-data-redis 裏面 ,而是不存在spring-boot-autoconfigure包,
既然如何,springboot又是如何找到配置類RedisAutoConfiguration的呢?
答案是條件註解。
4.1.3 條件註解確保配置類完成配置
小結,官方包的依賴就是條件觸發。
附:spring.factories中記錄官方包的配置類定位
這裏面這些都只需要導入依賴就好,只有第三方包才需要自己寫spring.factories。
4.2 demo spring.factories自定義組件的配置類的裝載
新建maven quickstart項目:autoconfiguredemo
spring.factories文件中指定配置類路徑
maven clean maven install 成爲一個jar包,給springboot工程去使用
新建一個maven quickstart 工程 springbootcore2,導入依賴
4.3 demo @ConditionalOnClass等註解實現條件配置
現在在第一個工程Configuration配置類上面使用條件註解,表示要滿足某一個條件才裝載,就使用 @ConditionalOnClass({RedisOperations.class}) 就好了。
先導入依賴
4.4 demo spring-autoconfigure-metadata.properties 實現條件配置
在springboot中存在一個spring-autoconfigure-metadata.properties文件,它也是一種配置文件。
這種配置文件只是,使用者需要按要求這樣配置,實際上我們自己的工程也可以實現這種配置文件並打成jar包的。
源工程
4.5 兩種配置方式一起使用
並不是所有的條件配置都是寫在類上面的註解上面的,也可以通過spring-autoconfigure-metadata.properties配置文件去寫,且看mybatis
這裏是mybatis的條件配置文件 spring-autoconfigure-metadata.properties
這裏是mybatis的條件註解
五、小結
本文介紹Springboot自動裝配的特性,從使用redis引入了自動裝配,然後理解自動裝配、模擬實現、閱讀springboot源碼,最後引入條件觸發和demo實現。
天天打碼,天天進步!!!
自動裝配模擬工程代碼:https://download.csdn.net/download/qq_36963950/12555256
SPI設計思想工程代碼:https://download.csdn.net/download/qq_36963950/12555258
自動裝配+條件註解+條件配置文件工程代碼:https://download.csdn.net/download/qq_36963950/12555260