SpringBoot自動裝配初步淺理解

来源:https://www.cnblogs.com/csrecord/archive/2022/07/01/16435628.html
-Advertisement-
Play Games

SpringBoot自動裝配原理 Created time: May 15, 2022 6:36 PM Done: Doing Last edited time: May 25, 2022 6:13 PM Tags: Spring, 後端, 總結 0 關於自動配置 pom.xml spring-bo ...


SpringBoot自動裝配原理

Created time: May 15, 2022 6:36 PM
Done: Doing
Last edited time: May 25, 2022 6:13 PM
Tags: Spring, 後端, 總結

0 關於自動配置

pom.xml

  • spring-boot-dependencies:核心依賴在父工程中
  • 在寫或者引入一些springboot依賴時,不需要指定版本,因為有這些版本倉庫。

啟動器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 啟動器,SpringBoot的啟動場景
  • spring-boot-starter-web 自動導入web環境所有的依賴
  • springboot會將所有的功能場景變成一個一個啟動器

主程式

//標註這個類是一個springboot的應用
@SpringBootApplication
public class Springboot01HelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }
}

1 SpringBoot四大核心

  • 四大核心
    • EnableAutoConfiguration自動裝配
    • Starter組件,開箱即用
    • Actutor監控
    • SpringBoot Cli為SpringCloud提供SpringBoot命令行功能

1.1 註解

在瞭解Spring註解之前先瞭解一些相關註解的知識。

//標註這個類是一個springboot的應用
@SpringBootApplication
//SpringBoot的配置
@SpringBootConfiguration
  @Configuration //Spring配置類
  @Component//本質還是一個Spring組件
//自動配置
@EnableAutoConfiguration
  @AutoConfigurationPackage//自動配置包
  @Import(AutoConfigurationPackages.Registrar.class)//導入選擇器包註冊
  @Import(AutoConfigurationImportSelector.class)//自動配置導入選擇(自動導入包的核心)
  //獲取所有的配置
  List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//getCandidateConfigurations獲取所有的候選配置**
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    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註解被SpringBootApplication繼承
	protected Class<?> getSpringFactoriesLoaderFactoryClass() {
	  return EnableAutoConfiguration.class;
	}

META-INF/spring.factories自動配置的核心文件

//所有的資源載入到類中
Properties properties = PropertiesLoaderUtils.loadProperties(resource);

結論

SpringBoot所有自動配置都是在啟動的時候掃描並載入:spring.factories所有的自動配置類都在這裡面,但不一定生效,要判斷條件是否成立,只要導入對應的start,就有對應的啟動器了,有了啟動器,自動裝配就會生效,然後就配置成功。

2 Enable註解作用

EnableAutoConfiguration 自動裝配相關的Eable註解.

開啟相關支持,如

  • EnableScheduling ,開啟計劃任務支持
  • EnableAutoConfiguration ,開啟自動裝配支持

EnableAutoConfiguration.java中涉及到Enable開頭的註解都會有一個@Import的註解

3 SpringBoot中的自動裝配原理

自動裝配作為Starter的基礎,也是SpringBoot的核心

SpringBoot的自動裝配是基於EnableAutoConfiguration 實現的,先瞭解一下傳統意義的自動裝配方式。

首先需要瞭解一些前置關於註解的知識

3.1 Configuration註解

Spring3以後,支持兩種配置bean的方式,一種xml文件方式和JavaConfig。

JavaConfig方式

Configuration 註解是JavaConfig形式基於Spring IOC容器配置類使用的一種註解。在啟動類裡邊標註@Configuration 也表示它是一個IOC容器的配置類。

public class DemoClass {

    public void say(){
        System.out.println("sya hello ... ");
    }
}
@Configuration
@Import(UserClass.class)
public class DemoConfiguration {

    @Bean
    public DemoClass getDemoClass(){
        return new DemoClass();
    }
}
public class DemoConfigurationMain {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(DemoConfiguration.class);
        DemoClass bean = ac.getBean(DemoClass.class);
        bean.say();
    }
}

3.2 Configuration本質

Configuration註解本質就是一個Component註解,會被AnnotationConfigApplicationContext 載入,而AnnotationConfigApplicationContextApplicationContext 的具體實現,會根據配置註解啟動應用上下文。所以在Main中通過AnnotationConfigApplicationContext 載入JavaConfig後,可以得到IOC容器中Bean的實例。

@Configuration  //也會被Spring容器托管,註冊到容器中,因為本身就是一個@Component
@ComponentScan("com.kuang.pojo")
@Import(MyConfig2.class)
public class MyConfig {

    //註冊一個Bean相當於之前寫的一個Bean標簽
    //這個方法的名字就相當於Bean標簽中的id屬性
    //這個方法的返回值,就相當於Bean標簽中的class屬性
    @Bean
    public User getUser(){
        return new User();  //返回要註入到Bean的對象
    }
}
public class MyTest {
    public static void main(String[] args) {
        //如果完全使用了配置類方式去做,只能通過AnnotationConfigApplicationContext來獲取容器,通過配置類的class對象載入
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User getUser = (User) context.getBean("getUser");
        System.out.println(getUser.getName());
    }
}
@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }

    @Value("xxx")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

3.3 ComponentScan註解

相當於xml配置文件中的context:component-scan ,主要作用是掃描指定路徑下標識了需要裝配的類,自動裝配到IOC容器中

@Configuration  //也會被Spring容器托管,註冊到容器中,因為本身就是一個@Component
@ComponentScan("com.kuang.pojo")
@Import(MyConfig2.class)
public class MyConfig {

    //註冊一個Bean相當於之前寫的一個Bean標簽
    //這個方法的名字就相當於Bean標簽中的id屬性
    //這個方法的返回值,就相當於Bean標簽中的class屬性
    @Bean
    public User getUser(){
        return new User();  //返回要註入到Bean的對象
    }
}

3.4 Import註解

等同於xml形式下的<import resource/> 註解,將多個分開的容器合併在一個容器中。

方式一:@Import,直接@Import(MyConfig2.class)

方式二:ImportSelector,動態載入實現ImportSelector介面

方式三:ImportBeanDefinitionRegistrar方式,實現ImportBeanDefinitionRegistrar 介面

3.5 深入EnableAutoConfiguration原理

EnableAutoConfiguration通過@Import(AutoConfigurationImportSelector.class) 導入第三方的提供的Bean配置類AutoConfigurationImportSelector

public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
        try {
// 載入META-INF/spring-autoconfigure-metadata.properties 下的元數據信息

            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 獲取候選載入的配置信息 META-INF/spring.factories
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 去掉重覆的配置信息
            configurations = this.removeDuplicates(configurations);
// 排序
            configurations = this.sort(configurations, autoConfigurationMetadata);
            // 獲取 註解中配置的 exclusion 信息
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 檢查
            this.checkExcludedClasses(configurations, exclusions);
// 移除需要排除的信息
            configurations.removeAll(exclusions);
// 過濾,檢查候選配置類上的註解@ConditionalOnClass,如果要求的類不存在,則這個候選類會被過濾不被載入
            configurations = this.filter(configurations, autoConfigurationMetadata);
// 廣播事件
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            // 返回要被載入的類數組
return (String[])configurations.toArray(new String[configurations.size()]);
        } catch (IOException var6) {
            throw new IllegalStateException(var6);
        }
    }
}

EnableAutoConfiguration 會幫助SpringBoot應用將所有符合@Configuration 配置都載入到當前SpringBoot創建的IOC容器,這裡面藉助了Spring框架提供的一個工具類SpringFactoriesLoader的支持。以及用到了Spring提供的條件註解@Conditional,選擇性的針對需要載入的bean進行條件過濾。

3.6 關於條件過濾

分析AutoConfigurationImportSelector的源碼時,會先掃描spring-autoconfiguration-metadata.properties文件,最後在掃描spring.factories對應的類時,會結合前面的元數據進行過濾,為什麼要過濾呢? 原因是很多的@Configuration其實是依托於其他的框架來載入的,如果當前的classpath環境下沒有相關聯的依賴,則意味著這些類沒必要進行載入,所以,通過這種條件過濾可以有效的減少@configuration類的數量從而降低SpringBoot的啟動時間。

4 總結

SpringBoot自動裝配實現是從classpath中搜尋spring.factory自動裝配的核心文件,將包下對應的org.springframework.boot.autoconfigure的配置項通過反射實例化為對應標註的@Configuration的JavaConfig形式的IOC容器配置類,將然後彙總為實例載入至IOC容器中。

備註:思路還是不太清晰,後續還需再整理一遍深入理解。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • bootstrap-select,selectpicker 用法詳細:通過官方文檔翻譯 用過selectpicker的都說好~但是網上中文的教程又找不到比較完整的用法,於是去官網看了下 順便弄過來翻譯一下: 選項可以通過數據屬性或JavaScript傳遞。對於數據屬性,附加選項名稱data-,如 d ...
  • Fundebug 前端異常監控服務 Fundebug提供專業的前端異常監控服務,我們的插件可以提供全方位的異常監控,可以幫助開發者第一時間定位各種前端異常,包括但不限於 JavaScript 執行錯誤以及 HTTP 請求錯誤。 並且,Fundebug 支持 Source Map 還原,記錄用戶行為以 ...
  • 前段時間研究了下基於`Prometheus`構建監控系統相關的概念,並以此為基準設計了一個企業級通用的監控告警平臺的方案。這裡分享一下架構的分析過程以及問題的解決思路。 ...
  • 本篇文章中,將描述如何使用go創建CA,並使用CA簽署證書。在使用openssl創建證書時,遵循的步驟是 創建秘鑰 > 創建CA > 生成要頒發證書的秘鑰 > 使用CA簽發證書。這種步驟,那麼我們現在就來嘗試下。 創建證書的頒發機構 首先,會從將從創建 CA 開始。CA 會被用來簽署其他證書 // ...
  • 本篇代碼提供者: 青燈教育-自游老師 [環境使用]: Python 3.8 Pycharm [模塊使用]: requests >>> pip install requests re json csv 如果安裝python第三方模塊: win + R 輸入 cmd 點擊確定, 輸入安裝命令 pip i ...
  • Java基礎之 數據類型 註釋、標識符、關鍵字 數據類型 類型轉換 變數、常量 運算符 包機制、JavaDoc 數據類型 強類型語言 要求變數的使用要嚴格符合會定,所有變數都必須先定義後才能使用 弱類型語言 變數的使用沒有那麼嚴格 什麼是位元組 位(bit):是電腦 內部數據 儲存的最小單位,110 ...
  • 今天看到一篇博客介紹使用 Lambda 表達式遞歸計算 n!。使用了 C++14 的 generic lambda,給 Lambda 表達式加了一個模板參數,在函數調用的時候將 Lambda 表達式作為參數傳遞給下一層函數。這種方法每次調用函數的時候都要比常規的函數多傳一個參數。我想起兩年前也用 L ...
  • 前言 有時候我們些代碼是總發此疑惑? 為什麼別人採集 xx 網站的時候能成功,而我卻總是不返回給數據 出現這種原因時往往是我們沒有給夠偽裝, 被識別了出來~ 就像人,你出門肯定是要穿衣服的對不,如果你不穿! 走在外面,肯定是最顯眼的一個,不抓你抓誰 還有一種就是明明我之前運行成功了,為什麼我現在再次 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...