Spring Boot 的自動配置原理

Spring Boot 的自動配置是其 "約定大于配置" 理念的核心實現,它能自動配置 Spring 應用所需的各種組件,大幅減少手動配置。下面從核心注解、加載流程、條件過濾等方面詳細講解其原理,并結合關鍵源碼說明。

一、自動配置的入口:@SpringBootApplication 注解

Spring Boot 應用的啟動類通常標注@SpringBootApplication,這個注解是自動配置的起點,它是一個 "復合注解",包含三個核心注解:

  • @SpringBootConfiguration:本質是@Configuration,標識當前類是配置類
  • @ComponentScan:掃描當前包及子包的組件(如@Component@Service等)
  • @EnableAutoConfiguration啟用自動配置的核心注解
源碼:@SpringBootApplication

java運行

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 等同于@Configuration
@ComponentScan(excludeFilters = { // 掃描組件@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
@EnableAutoConfiguration // 關鍵:啟用自動配置
public @interface SpringBootApplication {// 排除指定的自動配置類Class<?>[] exclude() default {};String[] excludeName() default {};// ... 其他屬性
}

二、@EnableAutoConfiguration:自動配置的開關

@EnableAutoConfiguration的核心作用是觸發 Spring 容器自動導入符合條件的配置類,其實現依賴@Import注解導入AutoConfigurationImportSelector類。

源碼:@EnableAutoConfiguration

java運行

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage // 自動注冊當前包為基礎包(用于掃描@Entity等)
@Import(AutoConfigurationImportSelector.class) // 關鍵:導入選擇器
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";// 排除不需要的自動配置類Class<?>[] exclude() default {};String[] excludeName() default {};
}

三、AutoConfigurationImportSelector:自動配置類的 "導入器"

AutoConfigurationImportSelector是自動配置的核心類,它通過selectImports方法篩選并導入符合條件的自動配置類,流程如下:

1. 核心方法:selectImports

該方法返回需要導入的自動配置類全類名數組,核心邏輯是獲取候選配置類并過濾。

java運行

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, etc. {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) { // 檢查是否啟用自動配置(默認啟用)return NO_IMPORTS;}// 1. 加載自動配置的元數據(條件注解等信息)AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);// 2. 獲取所有候選的自動配置類AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}// 關鍵:獲取自動配置入口(篩選候選類)protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {// ... 檢查是否啟用(省略)// 1. 獲取所有候選的自動配置類(從spring.factories加載)List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 2. 去重configurations = removeDuplicates(configurations);// 3. 排除用戶指定的自動配置類(通過exclude屬性)Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);// 4. 基于條件注解過濾(核心:只保留符合條件的配置類)configurations = filter(configurations, autoConfigurationMetadata);// ... 其他處理(發布事件等)return new AutoConfigurationEntry(configurations, exclusions);}
}
2. 加載候選配置類:getCandidateConfigurations

getCandidateConfigurations通過SpringFactoriesLoader從類路徑下的META-INF/spring.factories文件中加載自動配置類。

java運行

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// 從spring.factories中加載key為EnableAutoConfiguration的配置類List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. " +"If you are using a custom packaging, make sure that file is correct.");return configurations;
}// 指定加載的類型為EnableAutoConfiguration
protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}

四、SpringFactoriesLoader:SPI 機制的實現

SpringFactoriesLoader是 Spring 的一種 SPI(Service Provider Interface)實現,用于從類路徑的META-INF/spring.factories文件中加載指定類型的實現類

源碼:SpringFactoriesLoader.loadFactoryNames

java運行

public final class SpringFactoriesLoader {public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {String factoryTypeName = factoryType.getName();// 加載所有spring.factories文件,返回key為接口名、value為實現類列表的Mapreturn loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {// 查找類路徑下所有META-INF/spring.factories文件Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);// 解析文件為Properties(key=接口全類名,value=實現類全類名逗號分隔)Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}}
}
spring.factories 文件示例

Spring Boot 的spring-boot-autoconfigure包中包含META-INF/spring.factories,其中定義了大量自動配置類:

properties

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
# ... 其他數百個自動配置類

五、條件注解:過濾生效的自動配置類

spring.factories加載的候選配置類并非全部生效,Spring Boot 通過條件注解@Conditional系列)篩選符合當前環境的配置類。

常見條件注解:

  • @ConditionalOnClass:類路徑存在指定類時生效
  • @ConditionalOnMissingClass:類路徑不存在指定類時生效
  • @ConditionalOnBean:容器中存在指定 Bean 時生效
  • @ConditionalOnMissingBean:容器中不存在指定 Bean 時生效
  • @ConditionalOnProperty:配置文件中存在指定屬性時生效
  • @ConditionalOnWebApplication:當前是 Web 應用時生效
示例:DispatcherServletAutoConfiguration

Spring MVC 的 DispatcherServlet 自動配置類,通過條件注解控制生效時機:

java運行

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET) // 僅在Servlet Web應用中生效
@ConditionalOnClass(DispatcherServlet.class) // 類路徑存在DispatcherServlet時生效
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) // 在指定配置類之后加載
public class DispatcherServletAutoConfiguration {// 定義DispatcherServlet的Bean@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)@ConditionalOnMissingBean(DispatcherServlet.class) // 容器中沒有DispatcherServlet時才創建public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {DispatcherServlet dispatcherServlet = new DispatcherServlet();dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());// ... 配置其他屬性return dispatcherServlet;}
}

六、自動配置的完整流程總結

  1. 啟動觸發@SpringBootApplication包含@EnableAutoConfiguration,開啟自動配置。
  2. 導入選擇器@EnableAutoConfiguration通過@Import導入AutoConfigurationImportSelector
  3. 加載候選類AutoConfigurationImportSelector通過SpringFactoriesLoaderMETA-INF/spring.factories加載所有EnableAutoConfiguration對應的自動配置類。
  4. 過濾配置類
    • 排除用戶指定的類(exclude屬性)。
    • 通過條件注解(如@ConditionalOnClass)篩選符合當前環境的配置類。
  5. 注冊 Bean:生效的自動配置類(@Configuration)通過@Bean向容器注冊組件,完成自動配置。

通過這套機制,Spring Boot 實現了 "引入 starter 依賴即可自動配置組件" 的便捷性,開發者無需手動編寫大量 XML 或 Java 配置。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/98206.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/98206.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/98206.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

谷歌云平臺(Google Cloud Platform, GCP)介紹(全球領先的云計算服務平臺,為企業和開發者提供包括計算、存儲、數據分析、人工智能、機器學習、網絡和安全等在內的全面云服務)

文章目錄**1. GCP的核心優勢****1.1 全球領先的基礎設施****1.2 強大的數據分析和人工智能能力****1.3 卓越的安全性和合規性****1.4 靈活的定價模式****2. GCP的主要服務****2.1 計算服務****2.2 存儲和數據庫****2.3 網絡服務****2.4 人工智能與大數據****2.5 安全與管理工具…

RISC-V異常機制和異常定位

不少人在調試RISC-V core時&#xff0c;面對異常的出現不知所措&#xff0c;不知道如何定位代碼問題。這里將從RISC-V異常機制以及幾個異常實例學習下。 1 異常機制 1.1 什么是異常 異常是軟件程序員不得不要深入了解的&#xff0c;首先在學習異常機制前&#xff0c;對異常要…

c++中導出函數調用約定為__stdcall類型函數并指定導出函數名稱

開發環境在Visual studio 2022版本下&#xff0c;為防止編譯器重命名函數名稱&#xff08;會加上8等等亂七八糟的東西&#xff09;&#xff0c;我們對函數名稱進行指定&#xff1a;一、新建.def文件&#xff0c;名稱須與dll名稱相同&#xff0c;并放在與cpp文件相同文件夾下&am…

Vision Transformer (ViT) :Transformer在computer vision領域的應用(二)

METHOD,論文主要部分 In model design we follow the original Transformer (Vaswani et al., 2017) as closely as possible. An advantage of this intentionally simple setup is that scalable NLP Transformer architectures – and their efficient implementations –…

AI 論文周報丨紅隊測試語言模型/多視角 3D 點追蹤方法/蛋白質表示學習框架/密碼學漏洞檢測新框架……

近年來&#xff0c;已有若干方法嘗試從單目視頻實現 3D 點跟蹤&#xff0c;然而由于在遮擋和復雜運動等挑戰性場景中難以準確估計 3D 信息&#xff0c;這些方法的性能仍難以滿足實際應用對高精度與魯棒性的要求。 基于此&#xff0c;蘇黎世聯邦理工學院、卡內基梅隆大學聯合提出…

STM32 通過USB的Mass Storage Class讀寫掛載的SD卡出現卡死問題

問題描述&#xff1a;使用stm32cubemx生成的sdio和usb Mass Storage Class的代碼后&#xff0c;在USB_DEVICE\App\usbd_storage_if.c文件里面的接口調用以下函數出現卡死問題&#xff1a; SD_Driver.disk_initialize(0); SD_Driver.disk_read(lun, buf, blk_addr, blk_len) SD_…

Go語言中 error 接口與自定義錯誤類型的深入解析

在 Go 語言開發中&#xff0c;我們經常需要處理各種錯誤情況。Go 語言通過 error 接口提供了一套簡潔而強大的錯誤處理機制。然而&#xff0c;當涉及到自定義錯誤類型時&#xff0c;許多開發者會遇到一些令人困惑的問題。本文將通過一個實際案例來深入探討這個問題。 問題背景 …

字幕編輯工具推薦,Subtitle Edit v4.0.13發布:增強語音識別+優化翻譯功能

大家好呀&#xff0c;不知道大家有沒有做自媒體相關工作的呢&#xff0c;你們是不是也覺得剪輯視頻時最頭疼的往往不是畫面而是字幕&#xff0c;時間軸對不上、格式不兼容、需要手動翻譯&#xff0c;這些瑣碎工作消耗的精力甚至超過剪輯本身。 當你試遍各種在線工具卻發現要么…

【Java后端】Spring Boot 集成雪花算法唯一 ID

Spring Boot 實現基于雪花算法的分布式唯一 ID 生成器在分布式系統中&#xff0c;我們經常需要生成 全局唯一 ID&#xff0c;比如用戶 ID、訂單號、消息 ID 等。常見的方式有&#xff1a;數據庫自增主鍵、UUID、Redis/Zookeeper 分布式 ID 服務、百度 UidGenerator、美團 Leaf …

C語言初嘗試——洛谷

一、C數組&#xff1a;C 語言支持數組數據結構&#xff0c;它可以存儲一個固定大小的相同類型元素的順序集合。數組是用來存儲一系列數據&#xff0c;但它往往被認為是一系列相同類型的變量。聲明數組在 C 中要聲明一個數組&#xff0c;需要指定元素的類型和元素的數量&#xf…

C++八大排序

C排序算法一、概覽二、代碼實現1.冒泡排序2.插入排序3.希爾排序4.堆排序5.選擇排序6.快速排序7.歸并排序三、排序時間、空間復雜度總結排序&#xff0c;是C各大算法當中非常常見的一個步驟&#xff08;過程&#xff09;&#xff0c;通常我們使用便捷的algorithmalgorithmalgori…

每天五分鐘深度學習:深層神經網絡的優勢

本文重點 在人工智能領域,深層神經網絡(DNN)的崛起標志著技術范式的根本性轉變。相較于傳統淺層神經網絡(如單層感知機、線性回歸模型),深層網絡通過引入多層隱藏層,實現了對復雜數據模式的深度解析與高效建模。 深層神經網絡 神經網絡中輸入層表示神經網絡的第0層,…

相機幾何 空間點到像素平面轉換

一個空間中點到像素平面轉換&#xff0c;需要經過1. 空間坐標系轉換到相機坐標系2. 相機坐標系下3D點到相機平面轉換3. 相機平面到像素平面轉換相機三維空間到像素平面轉換1. 3D點到相機平面轉換2. 相機平面到像素平面轉換涉及到單位的轉換&#xff0c;和像素原點到相機平面原點…

webpack5 vue3同一倉庫,不同命令切換項目

技術方案&#xff1a;手動輸入不同的命令&#xff0c;啟動不同項目。實現這種能力本篇文章是通過不同路由劃分&#xff0c;進而實現不同項目的劃分。所以簡單來說就是通過輸入不同命令行在webpack中找到不同項目的路由&#xff0c;進而打不同項目的包&#xff0c;實現項目隔離。…

PowerBI實戰-制作帶有同比及趨勢線的雙柱狀圖

一、引言 今天的PowerBI報表的制作相對有一點復雜&#xff0c;我們直接根據最終展示圖來講解&#xff1a; 可以看到&#xff0c;我們今天要制作的圖像需要包括以下幾點&#xff1a;時間維度的趨勢、兩種不同維度的數據對比、不同數據標簽的展示、不同年份間環比的標簽展示以及…

物聯網智能網關配置教程:實現注塑機數據經基恩士PLC上傳至云平臺

一、項目背景隨著制造業向智能化、信息化方向快速發展&#xff0c;注塑車間作為塑料制品制造的核心環節&#xff0c;面臨著設備協議多樣、數據孤島嚴重、系統集成困難等問題。某大型注塑企業計劃對其老舊車間進行數字化改造&#xff0c;實現設備數據采集、遠程監控與MES系統對接…

【實戰】預警算法--噪聲添加機制

1. 背景 在多變量自聯想預測或異常檢測場景中&#xff0c;我們常使用帶噪自編碼器&#xff08;Denoising AutoEncoder&#xff0c;DAE&#xff09;來訓練模型&#xff0c;使模型能夠從帶噪輸入中重構原始數據。噪聲的添加方式對訓練效果、穩定性以及模型用途有顯著影響。 2. 兩…

ChromaDB探索

關于 ChromaDB、向量與 RAG 系統的核心知識問答總結 ??Q1: ChromaDB 是什么&#xff1f;它在數據庫領域中扮演什么角色&#xff1f;????A:?? ChromaDB 是一款開源的??向量數據庫??。它的核心角色是專門為 AI 應用&#xff08;如語義搜索、推薦系統、RAG&#xff09…

C# 基于halcon的視覺工作流-章33-矩狀測量

C# 基于halcon的視覺工作流-章33-矩狀測量 本章目標&#xff1a; 一、gen_measure_rectangle2準備提取垂直于矩形的直邊&#xff1b; 二、measure_pos 提取垂直于矩形或環形弧的直線邊緣&#xff1b; 三、measure_pairs提取垂直于矩形或環形弧長軸的直邊對&#xff1b; 四、匹配…

Day05_蒼穹外賣——Redis店鋪營業狀態設置

目錄1.1 Redis簡介1.2 Redis下載與安裝1.2.1 Redis下載1.2.2 Redis安裝1.3 Redis服務啟動與停止1.3.1 服務啟動命令1.3.2 客戶端連接命令1.3.3 修改Redis配置文件1.3.4 Redis客戶端圖形工具2. Redis數據類型2.1 五種常用數據類型介紹2.2 各種數據類型特點3. Redis常用命令3.1 字…