解讀SpringBoot為什么要用DeferredImportSelector
DeferredImportSelector 是 Spring Framework 3.1 引入的 ImportSelector 接口的增強版本,主要用于延遲加載配置類,提升 Spring Boot 應(yīng)用的啟動速度。
它允許在所有配置類處理完畢后,再根據(jù)其他配置類的信息選擇性地導(dǎo)入一些配置類。
為什么使用 DeferredImportSelector?
傳統(tǒng)的 ImportSelector 會在配置類解析的早期階段執(zhí)行,這意味著在選擇要導(dǎo)入的配置類時,它可能無法訪問完整的配置信息,導(dǎo)致無法做出最佳選擇。
DeferredImportSelector 解決了這個問題,它的執(zhí)行會被延遲到所有常規(guī)配置類都被處理之后,此時它可以訪問到所有配置類的信息,從而做出更明智的導(dǎo)入決策。
DeferredImportSelector 的工作原理
注冊: 當(dāng) Spring 容器解析配置類時,如果發(fā)現(xiàn)一個類實現(xiàn)了 DeferredImportSelector 接口,它不會立即執(zhí)行 selectImports() 方法,而是將該 DeferredImportSelector 的實例注冊到一個 DeferredImportSelectorHandler 中。
延遲執(zhí)行: 在所有配置類都處理完畢后,DeferredImportSelectorHandler 會負責(zé)執(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)。
返回要導(dǎo)入的配置類: selectImports() 方法返回一個 String 數(shù)組,包含了要導(dǎo)入的配置類的全限定名。 Spring 容器會根據(jù)這些全限定名來導(dǎo)入相應(yīng)的配置類,并注冊 Bean。
DeferredImportSelector 的優(yōu)勢
- 延遲加載: 避免過早加載不必要的配置類,提升啟動速度。
- 更智能的配置選擇: 基于已加載的配置信息,做出更精確的配置選擇。
- 條件化配置: 實現(xiàn)更復(fù)雜的條件化配置邏輯。
- 排序和分組: 控制
DeferredImportSelector的執(zhí)行順序。
DeferredImportSelector 的劣勢
- 更復(fù)雜: 比
ImportSelector更復(fù)雜,需要理解延遲加載和分組排序的機制。 - 調(diào)試難度增加: 由于是延遲執(zhí)行,調(diào)試時可能需要更多步驟。
DeferredImportSelector 的使用場景
- 自動配置: Spring Boot 的自動配置機制大量使用了
DeferredImportSelector。 例如,EnableAutoConfiguration注解使用AutoConfigurationImportSelector來選擇需要導(dǎo)入的自動配置類。 - 條件化配置: 根據(jù)某個 Bean 是否存在,或者某個配置屬性的值來選擇是否導(dǎo)入某個配置類。
- 模塊化: 將應(yīng)用分解為多個模塊,根據(jù)已加載的模塊信息來選擇導(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
// 可以訪問 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() {
// 實現(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() {
// 返回需要導(dǎo)入的類的列表,這里可以對entries進行排序,控制導(dǎo)入的順序
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 自動配置中的應(yīng)用
Spring Boot 的自動配置機制利用 DeferredImportSelector 實現(xiàn)了延遲加載和條件化配置。
@EnableAutoConfiguration注解: 這個注解觸發(fā)了自動配置機制。AutoConfigurationImportSelector:@EnableAutoConfiguration最終會使用AutoConfigurationImportSelector這個DeferredImportSelector。spring.factories文件:AutoConfigurationImportSelector從META-INF/spring.factories文件中讀取org.springframework.boot.autoconfigure.EnableAutoConfiguration鍵對應(yīng)的自動配置類列表。- 條件化過濾:
AutoConfigurationImportSelector會根據(jù) Spring 容器中的條件 (例如,是否存在某個 Bean,或者某個配置屬性的值) 來過濾這些自動配置類,只選擇符合條件的自動配置類進行導(dǎo)入。
總結(jié)
DeferredImportSelector 是 Spring Boot 中一個重要的特性,它允許延遲加載和條件化配置,從而提升應(yīng)用的啟動速度和靈活性。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC整合,出現(xiàn)注解沒有起作用的情況處理
這篇文章主要介紹了SpringMVC整合,出現(xiàn)注解沒有起作用的情況及處理,具有很好的參考價值,希望對大家有所幫助。2023-05-05
RestTemplate實現(xiàn)發(fā)送帶headers的GET請求
這篇文章主要介紹了RestTemplate實現(xiàn)發(fā)送帶headers的GET請求,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Springboot內(nèi)嵌tomcat應(yīng)用原理深入分析
懂得SpringBoot的童鞋應(yīng)該很清楚,不管應(yīng)用程序是屬于何種類型,都是一個Main方法走遍天下,對于web應(yīng)用,只需要引入spring-boot-starter-web中這個依賴,應(yīng)用程序就好像直接給我們來了個tomcat一樣,對于嵌入式Tomcat,其實也非常簡單,就是調(diào)用Tomcat提供的外部類2022-09-09
java調(diào)用shell命令并獲取執(zhí)行結(jié)果的示例
今天小編就為大家分享一篇java調(diào)用shell命令并獲取執(zhí)行結(jié)果的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07
Java實現(xiàn)學(xué)生成績管理系統(tǒng)
這篇文章主要為大家詳細介紹了Java實現(xiàn)學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04
詳解Java執(zhí)行g(shù)roovy腳本的兩種方式
這篇文章主要介紹了Java執(zhí)行g(shù)roovy腳本的兩種方式,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04

