解讀SpringBoot為什么要用DeferredImportSelector
DeferredImportSelector
是 Spring Framework 3.1 引入的 ImportSelector
接口的增強(qiáng)版本,主要用于延遲加載配置類,提升 Spring Boot 應(yīng)用的啟動(dòng)速度。
它允許在所有配置類處理完畢后,再根據(jù)其他配置類的信息選擇性地導(dǎo)入一些配置類。
為什么使用 DeferredImportSelector?
傳統(tǒng)的 ImportSelector
會(huì)在配置類解析的早期階段執(zhí)行,這意味著在選擇要導(dǎo)入的配置類時(shí),它可能無(wú)法訪問(wèn)完整的配置信息,導(dǎo)致無(wú)法做出最佳選擇。
DeferredImportSelector
解決了這個(gè)問(wèn)題,它的執(zhí)行會(huì)被延遲到所有常規(guī)配置類都被處理之后,此時(shí)它可以訪問(wèn)到所有配置類的信息,從而做出更明智的導(dǎo)入決策。
DeferredImportSelector 的工作原理
注冊(cè): 當(dāng) Spring 容器解析配置類時(shí),如果發(fā)現(xiàn)一個(gè)類實(shí)現(xiàn)了 DeferredImportSelector
接口,它不會(huì)立即執(zhí)行 selectImports()
方法,而是將該 DeferredImportSelector
的實(shí)例注冊(cè)到一個(gè) DeferredImportSelectorHandler
中。
延遲執(zhí)行: 在所有配置類都處理完畢后,DeferredImportSelectorHandler
會(huì)負(fù)責(zé)執(zhí)行所有注冊(cè)的 DeferredImportSelector
。
分組和排序 (可選): DeferredImportSelector
可以實(shí)現(xiàn) DeferredImportSelector.Group
接口,將多個(gè) DeferredImportSelector
分組,并按組進(jìn)行排序。 Spring Boot 允許對(duì) DeferredImportSelector.Group
進(jìn)行排序以控制執(zhí)行順序。
selectImports()
方法: 在 selectImports()
方法中,DeferredImportSelector
可以訪問(wèn)到整個(gè) Spring 容器的配置信息,例如:
- 已經(jīng)注冊(cè)的 Bean 定義。
- 已經(jīng)加載的配置類。
- 環(huán)境信息 (Environment)。
返回要導(dǎo)入的配置類: selectImports()
方法返回一個(gè) String 數(shù)組,包含了要導(dǎo)入的配置類的全限定名。 Spring 容器會(huì)根據(jù)這些全限定名來(lái)導(dǎo)入相應(yīng)的配置類,并注冊(cè) Bean。
DeferredImportSelector 的優(yōu)勢(shì)
- 延遲加載: 避免過(guò)早加載不必要的配置類,提升啟動(dòng)速度。
- 更智能的配置選擇: 基于已加載的配置信息,做出更精確的配置選擇。
- 條件化配置: 實(shí)現(xiàn)更復(fù)雜的條件化配置邏輯。
- 排序和分組: 控制
DeferredImportSelector
的執(zhí)行順序。
DeferredImportSelector 的劣勢(shì)
- 更復(fù)雜: 比
ImportSelector
更復(fù)雜,需要理解延遲加載和分組排序的機(jī)制。 - 調(diào)試難度增加: 由于是延遲執(zhí)行,調(diào)試時(shí)可能需要更多步驟。
DeferredImportSelector 的使用場(chǎng)景
- 自動(dòng)配置: Spring Boot 的自動(dòng)配置機(jī)制大量使用了
DeferredImportSelector
。 例如,EnableAutoConfiguration
注解使用AutoConfigurationImportSelector
來(lái)選擇需要導(dǎo)入的自動(dòng)配置類。 - 條件化配置: 根據(jù)某個(gè) Bean 是否存在,或者某個(gè)配置屬性的值來(lái)選擇是否導(dǎo)入某個(gè)配置類。
- 模塊化: 將應(yīng)用分解為多個(gè)模塊,根據(jù)已加載的模塊信息來(lái)選擇導(dǎo)入其他模塊的配置。
DeferredImportSelector 的示例
import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyDeferredImportSelector implements DeferredImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 可以獲取注解信息 importingClassMetadata // 可以訪問(wèn) Spring 容器中的 Bean 定義 // 根據(jù)條件選擇導(dǎo)入不同的配置類 if (conditionA()) { return new String[] { "com.example.config.ConfigA" }; } else { return new String[] { "com.example.config.ConfigB" }; } } private boolean conditionA() { // 實(shí)現(xiàn)條件邏輯 return true; // 示例:始終返回 true } }
示例:分組和排序
import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.core.type.AnnotationMetadata; import java.util.ArrayList; import java.util.List; import java.util.Objects; public class MyDeferredImportSelector implements DeferredImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.example.MyConfig"}; } @Override public Class<? extends Group> getImportGroup() { return MyGroup.class; } public static class MyGroup implements Group { private final List<Entry> entries = new ArrayList<>(); @Override public void process(AnnotationMetadata metadata, DeferredImportSelector importSelector) { // 可以根據(jù)metadata和importSelector的信息來(lái)決定是否添加entry entries.add(new Entry(metadata, importSelector.selectImports(metadata))); } @Override public Iterable<Entry> selectImports() { // 返回需要導(dǎo)入的類的列表,這里可以對(duì)entries進(jìn)行排序,控制導(dǎo)入的順序 return entries; } } }
如何使用 DeferredImportSelector
- 實(shí)現(xiàn)
DeferredImportSelector
接口: 創(chuàng)建一個(gè)類并實(shí)現(xiàn)DeferredImportSelector
接口,并重寫selectImports()
方法。 - 實(shí)現(xiàn)
getImportGroup()
方法 (可選): 如果需要分組和排序,則實(shí)現(xiàn)getImportGroup()
并返回一個(gè)實(shí)現(xiàn)了Group
接口的類。 - 注冊(cè)
DeferredImportSelector
: 可以通過(guò)@Import
注解,或者在META-INF/spring.factories
文件中注冊(cè)DeferredImportSelector
。
Spring Boot 自動(dòng)配置中的應(yīng)用
Spring Boot 的自動(dòng)配置機(jī)制利用 DeferredImportSelector
實(shí)現(xiàn)了延遲加載和條件化配置。
@EnableAutoConfiguration
注解: 這個(gè)注解觸發(fā)了自動(dòng)配置機(jī)制。AutoConfigurationImportSelector
:@EnableAutoConfiguration
最終會(huì)使用AutoConfigurationImportSelector
這個(gè)DeferredImportSelector
。spring.factories
文件:AutoConfigurationImportSelector
從META-INF/spring.factories
文件中讀取org.springframework.boot.autoconfigure.EnableAutoConfiguration
鍵對(duì)應(yīng)的自動(dòng)配置類列表。- 條件化過(guò)濾:
AutoConfigurationImportSelector
會(huì)根據(jù) Spring 容器中的條件 (例如,是否存在某個(gè) Bean,或者某個(gè)配置屬性的值) 來(lái)過(guò)濾這些自動(dòng)配置類,只選擇符合條件的自動(dòng)配置類進(jìn)行導(dǎo)入。
總結(jié)
DeferredImportSelector
是 Spring Boot 中一個(gè)重要的特性,它允許延遲加載和條件化配置,從而提升應(yīng)用的啟動(dòng)速度和靈活性。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java 字節(jié)數(shù)組類型(byte[])與int類型互轉(zhuǎn)方法
下面小編就為大家?guī)?lái)一篇Java 字節(jié)數(shù)組類型(byte[])與int類型互轉(zhuǎn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02mybatis update set 多個(gè)字段實(shí)例
這篇文章主要介紹了mybatis update set 多個(gè)字段實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01Java設(shè)置PDF有序和無(wú)序列表的知識(shí)點(diǎn)總結(jié)
在本篇文章中小編給大家整理了關(guān)于Java設(shè)置PDF有序和無(wú)序列表的知識(shí)點(diǎn),需要的朋友們參考下。2019-03-03json-lib將json格式的字符串,轉(zhuǎn)化為java對(duì)象的實(shí)例
下面小編就為大家?guī)?lái)一篇json-lib將json格式的字符串,轉(zhuǎn)化為java對(duì)象的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03Java使用Tessdata做OCR圖片文字識(shí)別的詳細(xì)思路
這篇文章主要介紹了Java使用Tessdata做OCR圖片文字識(shí)別的詳細(xì)思路,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07使用springboot單元測(cè)試對(duì)weblistener的加載測(cè)試
這篇文章主要介紹了使用springboot單元測(cè)試對(duì)weblistener的加載測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java實(shí)現(xiàn)醫(yī)院管理系統(tǒng)
這篇文章主要介為大家詳細(xì)紹了Java實(shí)現(xiàn)醫(yī)院管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12java調(diào)用ffmpeg實(shí)現(xiàn)轉(zhuǎn)換視頻
這篇文章主要為大家詳細(xì)介紹了java調(diào)用ffmpeg實(shí)現(xiàn)轉(zhuǎn)換視頻功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12java中hasNextInt判斷后無(wú)限循環(huán)輸出else項(xiàng)的解決方法
這篇文章主要介紹了java中hasNextInt判斷后無(wú)限循環(huán)輸出else項(xiàng)的解決方法的相關(guān)資料,需要的朋友可以參考下2016-10-10