Spring Boot 中的自動配置原理

2025/4/6

向全棧工程師邁進!

一、自動配置

所謂的自動配置原理就是遵循約定大約配置的原則,在boot工程程序啟動后,起步依賴中的一些bean對象會自動的注入到IOC容器中。

在講解Spring Boot 中bean對象的管理的時候,我們注入bean對象的過程如下,但這種方式不是自動注入的。?

并沒有達到自動配置。 而自動配置是當程序在引入spring-boot-starter-web 起步依賴,boot工程在啟動后,會自動往ioc容器中注入DispatcherServlet等bean對象,這就是自動配置。那自動配置的原理是什么呢?

二、自動配置原理

在這里只先引入springboot起步核心依賴,而并沒有引入spring-boot-starter-web起步依賴。

<!--引入springboot起步核心依賴-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>

在沒有引入spring-boot-starter-web依賴之前,我們嘗試輸出spring-boot-starter-web起步依賴會自動注入的bean對象,沒有在pom.xml文件中添加改起步依賴時,輸出發現根本沒有。

package com.example.demo;import org.springframework.context.ApplicationContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Demo1Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(Demo1Application.class, args);System.out.println(context.getBean("dispatcherServlet"));}}

導入依賴spring-boot-starter-web后,再次嘗試輸出其bean對象,發現成功,當引入依賴后,其bean對象被自動的注入了。

2.1 查看@SpringBootApplication注解源碼

是組合了以下三個注解

  • @SpringBootConfiguration 其本身也是一個組合注解
  • @EnableAutoConfiguration 其本身也是一個組合注解
  • @ComponentScan 是Bean掃描的注解

@SpringBootConfiguration的內部代碼:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Indexed;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

可以發現在@SpringBootConfiguration內部也是有@Configuration注解的,所以當在啟動類上添加注解@SpringBootApplication其實就是也在啟動類上添加了@Configuration注解,所以啟動類也是一個配置類。

@EnableAutoConfiguration的內部代碼:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

@EnableAutoConfiguration是自動配置的核心注解,該@EnableAutoConfiguration注解其實組合了@AutoConfigurationPackage和@Import兩個注解,在@Import注解中導入實現類AutoConfigurationImportSelector。其AutoConfigurationImportSelector的實現類如下(代碼不全):

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
........
import org.springframework.util.StringUtils;public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();private static final String[] NO_IMPORTS = new String[0];private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";private ConfigurableListableBeanFactory beanFactory;private Environment environment;private ClassLoader beanClassLoader;private ResourceLoader resourceLoader;private ConfigurationClassFilter configurationClassFilter;public AutoConfigurationImportSelector() {}............private MetadataReaderFactory getMetadataReaderFactory() {try {return (MetadataReaderFactory)this.beanFactory.getBean("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", MetadataReaderFactory.class);} catch (NoSuchBeanDefinitionException var2) {return new CachingMetadataReaderFactory(this.resourceLoader);}}}
}

?可以發現在這個實現類(AutoConfigurationImportSelector)中,會從 META-INF/spring.factories 文件中讀取所有自動配置類,它讀取的 key 是:

org.springframework.boot.autoconfigure.EnableAutoConfiguration

加載所有配置類,條件匹配后注冊為 Bean。

2.2 自動配置原理——舉個栗子🧩

核心:

AutoConfigurationImportSelector 會從 META-INF/spring.factories 文件中讀取所有自動配置類,它讀取的 key 是:org.springframework.boot.autoconfigure.EnableAutoConfiguration

? 你寫了一個 Spring Boot 項目,啟動類是這樣的:

@SpringBootApplication
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}

?這個注解其實包含了 @EnableAutoConfiguration,表示:

“嘿 SpringBoot,我想用你自動幫我配置一些常見功能,比如數據庫、Web、Redis 等!”

?🧠 那 SpringBoot 是怎么知道你要配置啥的?

這時候就輪到 AutoConfigurationImportSelector 出場了!

它是一個“選擇器”,全名叫:

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector

它的作用是:

🧭“我去找一個叫 spring.factories 的文件,里面寫了:SpringBoot 應該自動配置哪些類。我一個個加載它們,看看哪個需要用,哪個可以跳過。”

📂 spring.factories 是什么?

它是一個純文本配置文件,路徑在:

classpath:/META-INF/spring.factories

這個文件來自哪個 jar 包?👉 就是 Spring Boot 的依賴包之一:

spring-boot-autoconfigure-xxx.jar

打開看一下這個文件長什么樣:

# 配置項的 key
org.springframework.boot.autoconfigure.EnableAutoConfiguration=# 配置的值(每一行都是一個自動配置類,全限定類名)
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration

🌟 所以:Spring Boot 會遍歷所有這些類,一個個判斷:

  • 項目中有沒有用到數據庫?

  • 類路徑中有沒有 MySQL 驅動?

  • 你有沒有配置 spring.datasource.url

  • 有沒有你自己寫的 DataSource Bean?

滿足這些條件它就幫你創建這個 Bean;不滿足,它就跳過。

?如下是我真實項目中其spring.factories文件中的內容。

三、實現自動配置?

自動配置全過程如下:

?

山高路遠,我們慢些走,路邊有花,遠處有彩虹,西邊有落日......?

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

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

相關文章

Mysql8配置文件

Mysql8配置文件 修改my.cnf----配置持久化鍵(persistence key)配置表名不區分大小寫 修改my.cnf----配置持久化鍵(persistence key) MySQL8初始化數據庫之前配置好這些變量值&#xff0c;初始化數據庫之后可能無法修改這個值。 # 服務端配置 [mysqld] ######## 數據目錄和基…

關于系統架構思考,如何設計實現系統的高可用?

緒論、系統高可用的必要性 系統高可用為了保持業務連續性保障&#xff0c;以及停機成本量化&#xff0c;比如在以前的雙十一當天如果出現宕機&#xff0c;那將會損失多少錢&#xff1f;比如最近幾年Amazon 2021年30分鐘宕機損失$5.6M。當然也有成功的案例&#xff0c;比如異地…

【Unity筆記】實現可視化配置的Unity按鍵輸入管理器(按下/長按/松開事件 + UnityEvent綁定)

【Unity筆記】實現可視化配置的Unity按鍵輸入管理器 適用于角色控制、技能觸發的Unity按鍵輸入系統&#xff0c;支持UnityEvent事件綁定、長按/松開監聽與啟用開關 一、引言 在 Unity 游戲開發中&#xff0c;處理鍵盤輸入是最常見的交互方式之一。尤其是角色控制、技能釋放、菜…

Fortran 中使用 C_LOC 和 C_F_POINTER 結合的方法來實現不同類型指針指向同一塊內存區域

在 Fortran 中&#xff0c;可以使用 C_LOC 和 C_F_POINTER 結合的方法來實現不同類型指針指向同一塊內存區域。以下是具體方法和示例&#xff1a; 關鍵步驟&#xff1a; 獲取內存地址&#xff1a;用 C_LOC 獲取原始數組的 C 地址。類型轉換&#xff1a;用 C_F_POINTER 將地址轉…

Spring Boot整合Kafka的詳細步驟

1. 安裝Kafka 下載Kafka&#xff1a;從Kafka官網下載最新版本的Kafka。 解壓并啟動&#xff1a; 解壓Kafka文件后&#xff0c;進入bin目錄。 啟動ZooKeeper&#xff1a;./zookeeper-server-start.sh ../config/zookeeper.properties。 啟動Kafka&#xff1a;./kafka-server-…

【含文檔+PPT+源碼】基于微信小程序的學校體育館操場預約系統的設計與實現

課程簡介&#xff1a; 本課程演示的是一款基于微信小程序的學校體育館操場預約系統的設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從…

【Leetcode-Hot100】最大子數組和

題目 解答 class Solution(object):def maxSubArray(self, nums):""":type nums: List[int]:rtype: int"""len_nums len(nums)result -1e5left_fit, right_fit 0, len_nums-1if len_nums 1:return nums[0]sum_left, sum_right 0, 0while r…

txt、Csv、Excel、JSON、SQL文件讀取(Python)

txt、Csv、Excel、JSON、SQL文件讀取&#xff08;Python&#xff09; txt文件讀寫 創建一個txt文件 fopen(rtext.txt,r,encodingutf-8) sf.read() f.close() print(s)open( )是打開文件的方法 text.txt’文件名 在同一個文件夾下所以可以省略路徑 如果不在同一個文件夾下 ‘…

硬件電路設計之51單片機(2)

聲明&#xff1a;繪制原理圖和PCB的軟件為嘉立創EDA。根據B站尚硅谷嵌入式之原理圖&PCB設計教程學習所作個人用筆記。 目錄 一、原理圖詳解 1、TypeC接口 &#xff08;1&#xff09;TypeC接口介紹 &#xff08;2&#xff09;TypeC原理圖 2、5V轉3.3V 3、單片機電源開…

kubernetes 入門篇之架構介紹

經過前段時間的學習和實踐&#xff0c;對k8s的架構有了一個大致的理解。 1. k8s 分層架構 架構層級核心組件控制平面層etcd、API Server、Scheduler、Controller Manager工作節點層Kubelet、Kube-proxy、CRI&#xff08;容器運行時接口&#xff09;、CNI&#xff08;網絡插件&…

Flink CDC 出現錯誤碼 1236 和 SQL 狀態 HY000 的原因及解決方法

Flink CDC 出現錯誤碼 1236 和 SQL 狀態 HY000 的原因及解決方法 常見原因 server-id 沖突:當多個 Flink CDC 任務連接同一個 MySQL 實例,且使用了相同的 server-id 時,會導致該沖突。因為 MySQL 服務器通過 server-id 來區分不同的從服務器,如果多個 Flink CDC 任務使用相…

從PPT到PNG:Python實現的高效PPT轉圖工具

從PPT到PNG&#xff1a;Python實現的高效PPT轉圖工具 在日常工作中&#xff0c;PPT&#xff08;PowerPoint&#xff09;文件是我們常用的演示工具。然而&#xff0c;有時候我們需要將PPT的內容提取為圖片格式&#xff08;如PNG&#xff09;以便于展示或保存。手動將每一頁PPT保…

【開發語言】懸空指針問題

懸空指針&#xff08;Dangling Pointer&#xff09;是編程中常見的內存管理問題&#xff0c;尤其在C/C這類手動管理內存的語言中。以下是詳細解釋&#xff1a; 什么是懸空指針&#xff1f; 懸空指針是指向已經被釋放&#xff08;或失效&#xff09;內存的指針。這段內存可能已…

【持續更新中】常用docker服務部署指北

前言 docker是個好東西&#xff0c;小樹莓派上也能快速部署&#xff0c;方便管理環境。用這篇筆記來記錄下各種軟件的快速部署方式 準備環境 docker安裝 curl -fsSL https://get.docker.com -o get-docker.sh sh ./get-docker.shdocker鏡像源配置 一種方法是設置proxy&…

Godot學習-創建簡單動畫

文章目錄 1、準備工作Godot資源 2、創建項目3、創建結點4、創建動畫1、創建動畫2、添加軌道3、創建關鍵幀3.1 第一個關鍵幀3.2 第二個關鍵幀 5、加載后自動播放6、動畫循環7、軌道設置1、軌道更新模式2、軌跡插值3、其他屬性的關鍵幀4、編輯關鍵幀5、使用 RESET 軌道6、洋蔥皮 …

Python 爬蟲解決 GBK亂碼問題

文章目錄 前言爬取初嘗試與亂碼問題編碼知識科普UTF - 8GBKUnicode Python中的編碼轉換其他編碼補充知識GBKGB18030GB2312UTF&#xff08;UCS Transfer Format&#xff09;Unicode 總結 前言 在Python爬蟲的過程中&#xff0c;我嘗試爬取一本小說&#xff0c;遇到GBK亂碼問題&a…

B站搜索關鍵詞機制深度解析:算法邏輯與優化策略

在擁有超過5億用戶的B站生態系統中&#xff0c;每天都有海量的視頻內容被上傳和消費。對于創作者而言&#xff0c;如何讓自己的視頻在茫茫內容海洋中被目標受眾發現&#xff0c;是至關重要的課題。而關鍵詞&#xff0c;正是連接內容與用戶的關鍵橋梁。理解B站的搜索關鍵詞機制&…

寶塔面板中解鎖Laravel日志查看的奧秘

目錄 一、前言二、Laravel 日志基礎認知2.1 日志的作用2.2 Laravel 日志的默認配置 三、查找 Laravel 日志文件位置3.1 常規存儲路徑3.2 自定義路徑查找 四、查看 Laravel 日志內容4.1 寶塔面板文件管理器查看4.2 使用命令行查看 五、常見問題及解決方法5.1 權限不足無法查看5.…

Matlab Add Legend To Graph-圖例添加到圖

Add Legeng To Graph: Matlab的legend&#xff08;&#xff09;函數-圖例添加到圖 將圖例添加到圖 ,圖例是標記繪制在圖上的數據序列的有用方法。 下列示例說明如何創建圖例并進行一些常見修改&#xff0c;例如更改位置、設置字體大小以及添加標題。您還可以創建具有多列的圖…

K8S+Prometheus+Consul+alertWebhook實現全鏈路服務自動發現與監控、告警配置實戰

系列文章目錄 k8s服務注冊到consul prometheus監控標簽 文章目錄 系列文章目錄前言一、環境二、Prometheus部署1.下載2.部署3.驗證 三、kube-prometheus添加自定義監控項1.準備yaml文件2.創建新的secret并應用到prometheus3.將yaml文件應用到集群4.重啟prometheus-k8s pod5.訪…