【Java Web 快速入門】十一、Spring Boot 原理

目錄

  • Spring Boot 原理
    • 配置優先級
    • Bean 管理
      • 獲取 Bean
      • Bean 的作用域
      • 第三方 Bean
    • Spring Boot 底層原理
      • 起步依賴
      • 自動配置
        • 核心原理
        • 實例說明
          • 例 1:自定義一個 “日志 starter”
          • 例 2:SpringBoot 自帶的 spring-boot-starter-web
        • 關鍵總結

Spring Boot 原理

配置優先級

Spring Boot 中支持三種格式的配置文件:

  • application.properties

    server.port=8081
    
  • application.yml

    server:port: 8082
    
  • application.yaml

    server:port: 8083
    

在代碼中配置這三個文件,運行程序的結果如下;

在這里插入圖片描述

Tomcat 服務器在 8081 端口運行

如果只配置 application.yml 和 application.yaml,程序運行結果如下:

在這里插入圖片描述
Tomcat 服務器在 8082 端口運行

通過測試同一屬性在三個文件中的配置,得出優先級:properties 最高,yml 次之,yaml 最低。

Spring Boot 除了支持配置文件屬性配置,還支持 Java 系統屬性和命令行參數的方式進行屬性配置

  • Java系統屬性:-Dserver.port=9000
  • 命令行參數:--server.port=9001

命令行參數優先級高于 Java 系統屬性。

在 Spring Boot 項目打包后,若需配置屬性(如端口號等),可通過 Java 系統屬性命令行參數兩種方式進行,具體操作如下:

  1. 項目打包前提

    • 打包需執行 Maven 的package生命周期,生成可運行的 jar 包。

    • 注意:Spring Boot 項目打包必須依賴spring-boot-maven-plugin插件,基于官方骨架創建的項目會自動引入該插件,無需手動添加。

  2. 運行打包后的 jar 包

    • 基本命令:

      java -jar 項目名.jar
      
    • (例如:java -jar spring-boot-web-config.jar,可通過tab鍵自動補全 jar 包名稱)

  3. 配置 Java 系統屬性

    • 格式:在java命令后、-jar之前,使用-Dkey=value格式配置。

    • 示例:配置 Tomcat 端口號為 9000

      java -Dserver.port=9000 -jar spring-boot-web-config.jar
      
  4. 配置命令行參數

    • 格式:在 jar 包名稱之后,使用--key=value格式配置。

    • 示例:配置 Tomcat 端口號為 10010

      java -jar spring-boot-web-config.jar --server.port=10010
      

五種配置方式的優先級:從高到低依次為命令行參數、Java 系統屬性、properties 配置文件、yml 配置文件、yaml 配置文件。

Bean 管理

獲取 Bean

默認情況下,Spring 項目啟動時,會把 Bean 都創建好放在 IOC 容器中,如果想要主動獲取這些 Bean,可以通過以下方式:

  • 根據 name 獲取 Bean:Object getBean(String name)
  • 根據類型獲取 Bean:<T> T getBean(Class<T> requiredType)
  • 根據 name 獲取 Bean(帶類型轉換):<T> T getBean(String name, Class<T> requiredType)

在測試類中加入以下代碼進行獲取 Bean 的測試:

@Autowired
// 獲取ApplicationContext對象
private ApplicationContext applicationContext;
@Test
public void testGetBean(){// 根據Bean的名稱獲取DeptController bean1 = (DeptController) applicationContext.getBean("deptController");System.out.println(bean1);// 根據Bean的類型獲取DeptController bean2 = applicationContext.getBean(DeptController.class);System.out.println(bean2);// 根據Bean的名稱和類型獲取DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);System.out.println(bean3);
}

測試運行結果如下:

在這里插入圖片描述

三次調用 getBean 方法獲取同一 bean 對象,其地址值相同,說明默認情況下 bean 是單例的。

Spring 項目啟動時創建所有 bean 對象并放在 IOC 容器中,這僅針對默認情況下單例且非延遲加載的 bean,bean 的創建時間還受作用域和延遲初始化影響

Bean 的作用域

bean 是單例還是多例取決于其作用域,Spring 中 bean 支持五種作用域,重點關注前兩種,后三種在 web 環境生效:

作用域說明
singleton在整個 Spring 容器中,同名稱的 bean 對象只有一個實例,即單例,是作用域的默認值
prototype代表非單例,每一次使用該 bean 對象時,都會創建一個新的實例對象
request代表每一次請求對應一個實例對象
session代表每一次會話對應一個新的實例對象
application代表每一個應用對應一個實例對象

默認情況下,未設置作用域的 bean 是單例的,在 Spring 項目啟動、IOC 容器創建時就會實例化并放到容器中,多次獲取的是同一個對象。

設置 bean 作用域的方式:可以借助 Spring 中的 @Scope 注解來配置 bean 的作用域。

在要獲取 Bean 的類上添加 @Scope("prototype"),運行前面的測試代碼,結果如下:

在這里插入圖片描述

延遲初始化注解 @lazy:在類上添加 @lazy 注解后,bean 會延遲初始化,延遲到第一次使用的時候實例化。

注意事項:

  • 默認作用域為 singleton,默認單例 bean 在容器啟動時創建,可通過 @lazy 延遲到第一次使用時創建
  • prototype 非單例 bean 每次使用都會創建新實例

第三方 Bean

第三方 Bean 配置的必要性:項目中引入的第三方依賴提供的類(如 dom4j 中的 SAXReader),若每次使用都新建對象會耗費資源,需交給 Spring 的 IOC 容器管理,通過依賴注入使用。

第三方 Bean 配置的特殊之處:第三方類是只讀的,無法直接在類上添加 @Component 及其衍生注解聲明為 bean,需使用 @Bean 注解。

@Bean 注解的使用方法:在方法上添加 @Bean 注解,方法返回值為要管理的第三方 Bean 對象,Spring 會將方法返回值交給 IOC 容器管理,后續可通過 @Autowired 注入使用。

第三方 Bean 配置的位置:建議單獨定義配置類(用 @Configuration 標識),在配置類中集中配置第三方 bean。

第三方 Bean 的名稱規則:可通過 @Bean 的 name 或 value 屬性指定名稱,二者互為別名;未指定時,默認名稱為方法名。
第三方 Bean 聲明時的依賴注入:在定義第三方 bean 的方法中聲明對應類型的形參,Spring 容器會根據類型自動裝配 IOC 容器中的對應 Bean 對象。

Spring Boot 底層原理

Spring Boot 簡化開發的原因:底層提供起步依賴和自動配置兩個重要功能。起步依賴簡化 pom 文件依賴配置,解決 Spring 框架依賴配置繁瑣問題;自動配置簡化框架使用時 Bean 的聲明和配置,引入起步依賴后常見配置已存在,可直接使用。

起步依賴

以 Web 程序開發為例,使用 Spring 框架需引入多個依賴且版本需匹配,而使用 Spring Boot 只需引入對應的起步依賴(如 web 開發的 spring-boot-starter-web,aop 開發的 spring-boot-starter-aop)。其原理是 Maven 的依賴傳遞,起步依賴集成了開發所需的常見依賴,引入一個起步依賴后,其他依賴會通過依賴傳遞自動引入(若 A 依賴 B,B 依賴 C,C 依賴 D,引入 A 則 B、C、D 也會被引入)。

自動配置

自動配置的定義:指 Spring Boot 項目啟動時,除了用戶自己定義的 Bean 對象外,Spring Boot 會自動創建一些內置的配置類及 Bean 對象并放入 IOC 容器,使用戶在開發時無需手動聲明即可直接使用,簡化開發,省去繁瑣配置。

通過啟動 Spring Boot 工程,在控制臺的 Bean 中可查看所有 Bean 對象及配置類,包括用戶自己定義的和 Spring Boot 自動加載的配置類及其生成的 Bean 對象

在這里插入圖片描述

核心原理

自動配置的實現依賴 3 個關鍵機制:@EnableAutoConfiguration 注解SPI 機制(META-INF/spring.factories)條件注解(@Conditional)。三者協同工作,流程如下:

  1. 觸發點:@SpringBootApplication 注解

SpringBoot 項目的啟動類通常標注@SpringBootApplication,它是一個組合注解,包含 3 個核心注解:

  • @SpringBootConfiguration:標記當前類為配置類(類似@Configuration)。
  • @ComponentScan:默認掃描啟動類所在包及其子包(但自動配置不依賴它,而是通過其他機制加載外部包的 Bean)。
  • @EnableAutoConfiguration自動配置的 “開關”,正是這個注解觸發了后續的自動配置流程。
  1. 核心:@EnableAutoConfiguration 的作用

@EnableAutoConfiguration通過@Import(AutoConfigurationImportSelector.class)導入了AutoConfigurationImportSelector類,這個類是自動配置的 “核心執行者”,主要做兩件事:

  • 加載候選配置類:掃描類路徑下所有META-INF/spring.factories文件,讀取其中org.springframework.boot.autoconfigure.EnableAutoConfiguration對應的配置類全類名(這些是 “候選自動配置類”)。
  • 篩選有效配置類:通過spring.factories加載的候選配置類會經過條件注解(如@ConditionalOnClass)的篩選,只有滿足條件的配置類才會被真正加載到 IOC 容器。
  1. SPI 機制:META-INF/spring.factories 的作用

META-INF/spring.factories是 Java 的 SPI(Service Provider Interface)機制在 SpringBoot 中的應用,用于聲明 “自動配置類” 的位置
格式如下(key 固定為org.springframework.boot.autoconfigure.EnableAutoConfiguration,value 為自動配置類的全類名列表):

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration,\
com.example.OtherAutoConfiguration

當項目啟動時,AutoConfigurationImportSelector會讀取所有依賴中的spring.factories,收集所有聲明的自動配置類,作為候選者。

  1. 條件注解:篩選有效的配置類

候選配置類不會全部生效,需要通過條件注解判斷是否滿足生效條件。常見的條件注解有:

  • @ConditionalOnClass:類路徑下存在指定類時,配置類才生效(如引入spring-web依賴后,DispatcherServlet.class存在,Web 相關配置才生效)。
  • @ConditionalOnMissingBean:容器中不存在指定 Bean 時,配置類才生效(允許開發者自定義 Bean 覆蓋默認配置)。
  • @ConditionalOnProperty:配置文件中存在指定屬性時生效(如server.port配置觸發端口綁定)。

只有滿足所有條件的配置類,才會被 Spring 實例化,其內部定義的 Bean 才會被注冊到 IOC 容器。

總結流程:

  1. 啟動類標注@SpringBootApplication,觸發@EnableAutoConfiguration
  2. AutoConfigurationImportSelector掃描所有META-INF/spring.factories,收集候選自動配置類。
  3. 候選配置類通過條件注解篩選,保留有效配置類。
  4. 有效配置類被加載,其內部的 Bean(如DataSourceDispatcherServlet)被注冊到 IOC 容器。
實例說明

下面通過兩個例子(自定義 starter 和 SpringBoot 自帶 starter)直觀理解自動配置。

例 1:自定義一個 “日志 starter”

假設我們要開發一個my-log-starter,功能是:引入后自動配置一個LogServiceBean,用于打印日志。

步驟 1:定義核心 Bean 和配置類

  • LogService:需要被自動配置的 Bean。

    public class LogService {public void log(String message) {System.out.println("[MyLog] " + message);}
    }
    
  • LogAutoConfiguration:自動配置類,負責注冊LogService

    @Configuration  // 標記為配置類
    @ConditionalOnClass(LogService.class)  // 類路徑存在LogService時生效
    public class LogAutoConfiguration {// 注冊LogService到IOC容器@Bean@ConditionalOnMissingBean  // 若用戶自定義了LogService,則不使用默認的public LogService logService() {return new LogService();}
    }
    

步驟 2:通過 spring.factories 聲明自動配置類

src/main/resources下創建META-INF/spring.factories,聲明LogAutoConfiguration為候選配置類:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.log.LogAutoConfiguration

步驟 3:使用 starter

  • 其他項目引入

    my-log-starter
    

    依賴后,啟動項目時:

    1. AutoConfigurationImportSelector讀取spring.factories,發現LogAutoConfiguration
    2. 檢查到類路徑存在LogService.class(依賴已引入),且容器中沒有自定義的LogService,滿足條件。
    3. LogAutoConfiguration生效,logService()方法被執行,LogServiceBean 被注冊到 IOC 容器。
  • 開發者可直接注入使用:

    @RestController
    public class TestController {@Autowiredprivate LogService logService;  // 直接使用自動配置的Bean@GetMapping("/test")public String test() {logService.log("測試日志");  // 輸出:[MyLog] 測試日志return "ok";}
    }
    
例 2:SpringBoot 自帶的 spring-boot-starter-web

引入spring-boot-starter-web后,SpringBoot 會自動配置 Web 開發所需的核心組件(如 Tomcat、DispatcherServlet),原理如下:

  1. 依賴引入starter-web包含spring-webspring-webmvctomcat-embed-core等依賴。
  2. 自動配置類spring-boot-autoconfigure包的META-INF/spring.factories中聲明了DispatcherServletAutoConfigurationTomcatAutoConfiguration等配置類。
  3. 條件判斷:
    • TomcatAutoConfiguration通過@ConditionalOnClass(Tomcat.class)判斷:因引入了tomcat-embed-core,Tomcat 類存在,配置生效,自動啟動內嵌 Tomcat。
    • DispatcherServletAutoConfiguration通過@ConditionalOnClass(DispatcherServlet.class)判斷:因引入spring-webmvc,DispatcherServlet 類存在,配置生效,注冊DispatcherServlet到容器。
  4. 最終效果:開發者無需手動配置 Tomcat 和 DispatcherServlet,引入依賴即可開發 Web 接口。
關鍵總結
  1. 自動配置的核心是:通過 @EnableAutoConfiguration 觸發,SPI 機制加載候選配置類,條件注解篩選有效配置類
  2. 開發者可通過自定義 starter(含spring.factories和自動配置類)實現自動配置,也可通過@ConditionalOnMissingBean等注解覆蓋默認配置。
  3. SpringBoot 的 starter(如webdata-jpa)都是基于此原理實現,極大簡化了配置流程。

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

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

相關文章

基于Redisson的分布式鎖原理深度解析與優化實踐

基于Redisson的分布式鎖原理深度解析與優化實踐 分布式環境下&#xff0c;鎖的實現至關重要。本文將從技術背景與應用場景出發&#xff0c;結合核心原理、關鍵源碼、實際示例&#xff0c;深入剖析Redisson分布式鎖的實現機制&#xff0c;并給出性能優化建議&#xff0c;幫助后端…

室外 3DVG 基準

室外 3DVG基準&#xff08;按重要性與被引用頻率&#xff09; Talk2Car / Talk2Car-3D (2019 / 衍生) — 對象 referral&#xff08;駕駛場景&#xff09; 說明&#xff1a;最早的自然語言 → 駕駛場景對象引用數據集之一&#xff08;原 Talk2Car 是以 nuScenes 為底并提供自然…

Jenkins安裝部署(Win11)和常見配置鏡像加速

一、安裝前準備 本文使用的Jenkins Windows一鍵安裝包&#xff0c;JDK事先配置好環境變量&#xff0c;Jenkins版本&#xff1a; Jenkins下載地址&#xff1a;jenkins一鍵安裝包v2-479-1.msi資源-CSDN下載 二、Jenkins安裝部署 1、下載Jenkins &#xff0c;點擊下一步下一步…

Windows MCP.Net:革命性的 .NET Windows 桌面自動化 MCP 服務器

&#x1f4cb; 目錄 項目概述 核心技術架構 功能特性詳解 技術實現亮點 安裝與配置 實戰應用場景 代碼示例與API詳解 性能優化與最佳實踐 未來發展規劃 總結 項目概述 在人工智能快速發展的今天&#xff0c;AI 助手與操作系統的深度集成成為了一個重要趨勢。Window…

Java ArrayList的介紹及用法

十分想念順店雜可。。。ArrayList 是 Java 集合框架中最常用的類之一&#xff0c;實現了 List 接口&#xff0c;底層基于動態數組實現&#xff0c;支持動態擴容&#xff0c;相比普通數組更靈活。以下是其詳細介紹及用法&#xff1a;一、核心特性動態大小&#xff1a;無需預先指…

Docker 命令大全及使用場景總結

一、容器生命周期管理1. 創建并運行容器docker run [選項] 鏡像名 [命令]常用選項&#xff1a;-d&#xff1a;后臺運行&#xff08;detached&#xff09;-it&#xff1a;交互式終端&#xff08;如 -it ubuntu bash&#xff09;--name&#xff1a;指定容器名稱-p 主機端口:容器端…

簡單的 HTTPS 學習

簡單的 HTTPS 學習 1. 需求 現在使用的服務是HTTP調用形式&#xff0c;服務可能會有調用外圍https形式的服務&#xff0c;簡單了解了一下&#xff0c;然后寫了一個簡單的例子進行記錄。 HTTP&#xff08;超文本傳輸協議&#xff09; 是一種用于傳輸超文本的應用層協議&#…

[系統架構設計師]系統質量屬性與架構評估(八)

[系統架構設計師]系統質量屬性與架構評估&#xff08;八&#xff09; 一.軟件系統質量屬性 1.基本概念 軟件系統質量屬性&#xff1a;可測量或可測試的屬性 開發期質量屬性&#xff0c;運行期質量屬性面向架構評估的質量屬性&#xff1a;1.可用性&#xff1a; 提升策略 錯誤檢測…

【R語言】R 語言中 gsub 與正則表達式詳解(含 POSIX 與 Perl 風格實例)

R 語言中 gsub 與正則表達式詳解&#xff08;含 POSIX 與 Perl 風格實例&#xff09; 在 R 語言中&#xff0c;字符串處理是非常常見的需求&#xff0c;R 語言中的 gsub() 函數則具有字符串替換的功能。本文將通過兩個實例&#xff0c;幫助你深入理解 R 的 gsub()、POSIX 字符…

EN55035多媒體設備電磁兼容性抗干擾要求標準

EN55035 是一項由歐洲標準化委員會制定的電磁兼容性&#xff08;EMC&#xff09;標準&#xff0c;全稱為《多媒體設備的電磁兼容性要求》。該標準主要針對多媒體設備的電磁輻射和抗干擾能力進行規范&#xff0c;確保這類設備在電磁環境中能夠正常工作&#xff0c;同時不對其他設…

計算分組內時間列的最大差值

計算分組內時間列的最大差值 在 Pandas 中&#xff0c;要計算每個分組內 time 列的最大值與當前行值的差值&#xff0c;需結合 groupby() 和 transform() 方法。核心步驟如下&#xff1a;分組計算最大值 使用 transform(max) 獲取每個分組中 time 列的最大值&#xff0c;結果會…

CUDA 編程筆記:CUDA延遲隱藏

一、核心概念&#xff1a;延遲隱藏&#xff08;Latency Hiding&#xff09;是 GPU 通過多線程機制掩蓋指令延遲的關鍵技術。當某些線程束&#xff08;warp&#xff09;因指令延遲&#xff08;如內存訪問或算術計算&#xff09;而等待時&#xff0c;其他就緒線程束會立即被調度執…

MySQL工具包中的其他程序

雖然有很多不同的程序&#xff0c;但有些選項是公共的&#xff0c;比兔用戶名和密碼&#xff0c;使用方法和MySQL相同&#xff0c;在這里統一列出&#xff0c;后面我們介紹不同的工具時&#xff0c;只討論個性的選項以及作用以下是常用的MySQL程序&#xff1a;程序名作用mysqld…

C#WPF實戰出真汁09--【消費開單】--選擇菜品

1、功能介紹當選擇一個空桌時&#xff0c;必須先開臺才能開單&#xff0c;可以先開臺&#xff0c;再開單&#xff0c;也可以開臺的同時開單當選擇一個用餐中的餐桌時&#xff0c;必須顯示該桌前面已經點好的菜品&#xff0c;同時可以繼續點餐或結賬所以無論哪個功能都涉及選擇菜…

大廠語音合成成本深度對比:微軟 / 阿里 / 騰訊 / 火山 API 計費拆解與技術選型指南

在 AI 配音、智能客服、教育音頻等場景爆發的當下&#xff0c;語音合成 API 已成為企業技術棧中的核心組件。然而&#xff0c;不同云廠商的計費規則差異顯著&#xff0c;短文本 / 長文本計費分離、預付費 / 后付費價格梯度懸殊、音色授權費暗藏成本陷阱等問題&#xff0c;常導致…

Flutter開發 網絡請求

HttpClient&#xff08;dart自有&#xff09; 1.get 點擊請求按鈕獲取數據&#xff0c;解析數據獲取單詞展示到屏幕上。class MyState extends State {String info "暫無數據";List<Widget> texts [];overridevoid initState() {super.initState();}override…

vscode中用python調用matlab的函數(環境安裝)

本實踐適用于WIN11-x64和ubuntu22.04-x64系統&#xff0c;其余系統和架構未驗證。 效果展示 1.環境要求 MATLAB Engine API for Python 的系統要求&#xff1a;參閱此官方文檔MATLAB 與 Python 的版本兼容性&#xff1a;參閱此官方文檔 2.安裝步驟 安裝Vscode&#xff08;不…

【數據分享】大清河(大慶河)流域上游土地利用

而今天要說明數據就是大清河&#xff08;大慶河&#xff09;流域上游土地利用。數據介紹大清河&#xff0c;又稱大慶河&#xff0c;作為海河流域的重要支流&#xff0c;其流域上游地區不僅是區域水資源調控的關鍵節點&#xff0c;更是生態保護與經濟發展的重要載體。以下從地理…

圖論——Djikstra最短路

原理解釋 首先解釋一下它大概的應用場景以及原理&#xff1a;現在有這么一張圖&#xff0c;圖上各點之間都有一定的邊權或者說是距離。給定你一個起點&#xff08;例如點1&#xff09;&#xff0c;讓你求這個點到圖上所有點的最短距離是多少&#xff1f; 這個問題比較平常&…

kafka初步介紹

Kafka角色介紹TopicTopic主題的意思&#xff0c;消費者必須指定主題用于的消息發送&#xff0c;生產者也必須指定主題用于消息的接收。topic只是邏輯上的劃分。partitionpartition是分區的意思&#xff0c;他的主要作用是將發送到一個topic的數據做一個劃分。如果有4個partitio…