springboot的自動配置

来源:https://www.cnblogs.com/pavi/archive/2020/03/07/12437314.html
-Advertisement-
Play Games

1. 起因 ​ 使用springboot也有些時間,一直很好奇它如何做到自動配置的,所以查閱了相關資料並且學習了相關內容,才寫了這篇文章。 2. 分析 ​ ①第一步我們從它的啟動配置類(XxxApplication)收起,我們進入到他的@SpringBootApplication註解。 ​ ②我們可 ...


1. 起因

​ 使用springboot也有些時間,一直很好奇它如何做到自動配置的,所以查閱了相關資料並且學習了相關內容,才寫了這篇文章。

2. 分析

​ ①第一步我們從它的啟動配置類(XxxApplication)收起,我們進入到他的@SpringBootApplication註解。
在這裡插入圖片描述

​ ②我們可以看到如下代碼,由於我們需要找到導致它自動配置的,所以鎖定了@EnableAutoConfiguration註解,那麼就可以進入這個註解。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

在這裡插入圖片描述

​ ③ 我們看到瞭如下代碼,由於這是一個介面,而它的實現類我們又不好確定,所以我們只好從註解入手,由於@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited等都是元註解,我們可以從@AutoConfigurationPackage,@Import({AutoConfigurationImportSelector.class})中找到我們想要的,根據它的中文意思我們可以從@Import({AutoConfigurationImportSelector.class})(自動有選擇的導入配置)出發,畢竟不是所有的配置都會都如,而導入那些配置根據項目中使用了那些starter決定。
在這裡插入圖片描述

​ ④點入第三步提到的註解,進入這個類根據方法名我們可以猜測是和這個方法相關,通過閱讀這個代碼,我們可以猜測是和getAutoConfigurationEntry這個方法有關,所以不妨點進去。

 public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata =        AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

​ ⑤由於我們需要的配置Config,所以大致可以斷定是和這個代碼有關聯List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);,所以不妨進到這個getCandidateConfigurations方法中去。

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

​ ⑥經過第五步,我們可以看到如下代碼

 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

不妨看這部分代碼,List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());,它的意思是一個載入器通過載入某個工廠獲得配置的List,因此我們在進入到這個的實現是沒有必要的,可以從參數考慮,所以鎖定在第一個參數,點進入可以看到如下代碼。

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

看到這裡可能還是會疑惑?為啥就自動配置了,其實我們這個方法(loadFactoryNames)是從一個配置文件中讀取內容,它的鍵是EnableAutoConfiguration,而這個配置文件是在如圖所示的文件中。

在這裡插入圖片描述
在這裡插入圖片描述

⑥打開上述文件,根據上一步的鍵找它的值,如圖就是springboot配置類,那麼項目啟動時是不是所有的配置都起作用嗎?不妨進入到某個配置類查看即可。如圖所示的@ConditionalOnMissingBean註解表示項目的容器是否有這個bean,如果沒有這個配置類就不會其作用,另外我們只要在仔細看這個類首先進行了初始化,之後它會從配置文件(application.xml或者application.yml)中獲取值。
在這裡插入圖片描述

註:如有錯誤,歡迎指出。


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

-Advertisement-
Play Games
更多相關文章
  • 前面知道NumPy是 Python 語言的一個擴展程式庫,支持大量的維度數組與矩陣運算,也針對數組運算提供大量的數學函數庫。numpy是基於c語言開發,所以這使得numpy的運行速度很快,高效率運行就是numpy的一大優勢。但numpy的特長並不是在於數據處理,而是在於能非常方便地實現科學計算,所以 ...
  • 什麼是Dubbo Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。 什麼是RPC RPC全稱(Remote Procedure Call)遠程過程調用 過程指的是某個代碼片段的執行,遠程調用則意味著我 ...
  • Java的三魂七魄之一:多線程。本文章帶你瞭解多線程的多個知識點,包括多線程的創建、線程安全問題、線程通信問題... ...
  • 1、while迴圈 使用while列印1.2.3.4.5.6.8.9.10 #快速註釋Ctrl+?count = 1 while count <= 10: if count == 7: count = count + 1 pass #表示過,不執行下麵程式 else: print(count) co ...
  • 1.PHP語法基礎是否都會,比如異常捕捉,面向對象,數組操作語法,字元串操作,cookie,session,全局變數,超全局數組,防止sql註入,mysql預處理 2.MYSQL基礎語法,欄位設計,原生sql語句,如何優化查詢效率,索引如何使用,分組聚合,表關聯(一對多,多對多),分庫分表, 3.服 ...
  • 如何使用python將大量數據導出到Excel中的小技巧 (1) 問題描述:為了更好地展示數據,Excel格式的數據文件往往比文本文件更具有優勢,但是具體到python中,該如何導出數據到Excel呢?如果碰到需要導出大量數據又該如何操作呢?本文主要解決以上兩個問題。 PS註意:很多人學Python ...
  • 視頻地址:https://www.bilibili.com/video/av59676843/?p=631 課件、源碼及習題:鏈接:https://pan.baidu.com/s/1Jt59yZfuK-4j7sYZgzmUqA 提取碼:yz8l 習題答案:https://www.cnblogs.co ...
  • 1、Mac下安裝requests庫: pip3 install requests 2、requests庫的使用 2.1 發送請求 使用Requests發送網路請求第一步,導入requests模塊: import requests 嘗試獲取某個網頁。如百度首頁: r = requests.get('h ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...