解讀SpringBoot為什么要用DeferredImportSelector
DeferredImportSelector
是 Spring Framework 3.1 引入的 ImportSelector
接口的增強版本,主要用于延遲加載配置類,提升 Spring Boot 應用的啟動速度。
它允許在所有配置類處理完畢后,再根據(jù)其他配置類的信息選擇性地導入一些配置類。
為什么使用 DeferredImportSelector?
傳統(tǒng)的 ImportSelector
會在配置類解析的早期階段執(zhí)行,這意味著在選擇要導入的配置類時,它可能無法訪問完整的配置信息,導致無法做出最佳選擇。
DeferredImportSelector
解決了這個問題,它的執(zhí)行會被延遲到所有常規(guī)配置類都被處理之后,此時它可以訪問到所有配置類的信息,從而做出更明智的導入決策。
DeferredImportSelector 的工作原理
注冊: 當 Spring 容器解析配置類時,如果發(fā)現(xiàn)一個類實現(xiàn)了 DeferredImportSelector
接口,它不會立即執(zhí)行 selectImports()
方法,而是將該 DeferredImportSelector
的實例注冊到一個 DeferredImportSelectorHandler
中。
延遲執(zhí)行: 在所有配置類都處理完畢后,DeferredImportSelectorHandler
會負責執(zhí)行所有注冊的 DeferredImportSelector
。
分組和排序 (可選): DeferredImportSelector
可以實現(xiàn) DeferredImportSelector.Group
接口,將多個 DeferredImportSelector
分組,并按組進行排序。 Spring Boot 允許對 DeferredImportSelector.Group
進行排序以控制執(zhí)行順序。
selectImports()
方法: 在 selectImports()
方法中,DeferredImportSelector
可以訪問到整個 Spring 容器的配置信息,例如:
- 已經(jīng)注冊的 Bean 定義。
- 已經(jīng)加載的配置類。
- 環(huán)境信息 (Environment)。
返回要導入的配置類: selectImports()
方法返回一個 String 數(shù)組,包含了要導入的配置類的全限定名。 Spring 容器會根據(jù)這些全限定名來導入相應的配置類,并注冊 Bean。
DeferredImportSelector 的優(yōu)勢
- 延遲加載: 避免過早加載不必要的配置類,提升啟動速度。
- 更智能的配置選擇: 基于已加載的配置信息,做出更精確的配置選擇。
- 條件化配置: 實現(xiàn)更復雜的條件化配置邏輯。
- 排序和分組: 控制
DeferredImportSelector
的執(zhí)行順序。
DeferredImportSelector 的劣勢
- 更復雜: 比
ImportSelector
更復雜,需要理解延遲加載和分組排序的機制。 - 調試難度增加: 由于是延遲執(zhí)行,調試時可能需要更多步驟。
DeferredImportSelector 的使用場景
- 自動配置: Spring Boot 的自動配置機制大量使用了
DeferredImportSelector
。 例如,EnableAutoConfiguration
注解使用AutoConfigurationImportSelector
來選擇需要導入的自動配置類。 - 條件化配置: 根據(jù)某個 Bean 是否存在,或者某個配置屬性的值來選擇是否導入某個配置類。
- 模塊化: 將應用分解為多個模塊,根據(jù)已加載的模塊信息來選擇導入其他模塊的配置。
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 // 可以訪問 Spring 容器中的 Bean 定義 // 根據(jù)條件選擇導入不同的配置類 if (conditionA()) { return new String[] { "com.example.config.ConfigA" }; } else { return new String[] { "com.example.config.ConfigB" }; } } private boolean conditionA() { // 實現(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的信息來決定是否添加entry entries.add(new Entry(metadata, importSelector.selectImports(metadata))); } @Override public Iterable<Entry> selectImports() { // 返回需要導入的類的列表,這里可以對entries進行排序,控制導入的順序 return entries; } } }
如何使用 DeferredImportSelector
- 實現(xiàn)
DeferredImportSelector
接口: 創(chuàng)建一個類并實現(xiàn)DeferredImportSelector
接口,并重寫selectImports()
方法。 - 實現(xiàn)
getImportGroup()
方法 (可選): 如果需要分組和排序,則實現(xiàn)getImportGroup()
并返回一個實現(xiàn)了Group
接口的類。 - 注冊
DeferredImportSelector
: 可以通過@Import
注解,或者在META-INF/spring.factories
文件中注冊DeferredImportSelector
。
Spring Boot 自動配置中的應用
Spring Boot 的自動配置機制利用 DeferredImportSelector
實現(xiàn)了延遲加載和條件化配置。
@EnableAutoConfiguration
注解: 這個注解觸發(fā)了自動配置機制。AutoConfigurationImportSelector
:@EnableAutoConfiguration
最終會使用AutoConfigurationImportSelector
這個DeferredImportSelector
。spring.factories
文件:AutoConfigurationImportSelector
從META-INF/spring.factories
文件中讀取org.springframework.boot.autoconfigure.EnableAutoConfiguration
鍵對應的自動配置類列表。- 條件化過濾:
AutoConfigurationImportSelector
會根據(jù) Spring 容器中的條件 (例如,是否存在某個 Bean,或者某個配置屬性的值) 來過濾這些自動配置類,只選擇符合條件的自動配置類進行導入。
總結
DeferredImportSelector
是 Spring Boot 中一個重要的特性,它允許延遲加載和條件化配置,從而提升應用的啟動速度和靈活性。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java 字節(jié)數(shù)組類型(byte[])與int類型互轉方法
下面小編就為大家?guī)硪黄狫ava 字節(jié)數(shù)組類型(byte[])與int類型互轉方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02json-lib將json格式的字符串,轉化為java對象的實例
下面小編就為大家?guī)硪黄猨son-lib將json格式的字符串,轉化為java對象的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03使用springboot單元測試對weblistener的加載測試
這篇文章主要介紹了使用springboot單元測試對weblistener的加載測試,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10java中hasNextInt判斷后無限循環(huán)輸出else項的解決方法
這篇文章主要介紹了java中hasNextInt判斷后無限循環(huán)輸出else項的解決方法的相關資料,需要的朋友可以參考下2016-10-10