spring boot啟動源碼分析(三)之Environment準備

上一篇《spring-boot啟動源碼分析(二)之SpringApplicationRunListener》

環境介紹:

spring boot版本:2.7.18

主要starter:spring-boot-starter-web

本篇開始講啟動過程中Environment環境準備,Environment是管理所有配置的實例對象,像application.yml、系統屬性、環境變量等配置都可以通過Environment.getProperty(key)獲取

入口如下:

(一)創建ConfigurableEnvironment

首先會從spring.factories中獲取ApplicationContextFactory.class接口實現類,根據webApplicationType會實例化對應的ConfigurableEnvironment(這里是SERVLET,所以是AnnotationConfigServletWebServerApplicationContext.Factory創建的ApplicationServletEnvironment)

ApplicationServletEnvironment的類結構如下:

ApplicationServletEnvironment調用構造方法實例化時,父類AbstractEnvironment構造方法中會有初始化操作:

propertySources是Environment的核心屬性,包含了各個配置源,這里賦值了一個MutablePropertySources,它實際是一個迭代器:

propertyResolver:是屬性解析器,如占位符的解析等

AbstractEnvironment構造器采用類似模板方法將customizePropertySources(propertySources)交給子類實現,子類可以在此方法中加載數據源

可以看到子類StandardServletEnvironment,添加了StubPropertySource,樁配置源,類似打樁,這兩個樁配置源分別是servletConfigInitParams和servletContextInitParams。這兩個在webserver啟動后會被替換成實際的配置源,這里只是個站位,沒有實際的作用。

之后再次調用超類的customizePropertySources:

在StandardEnvironment中會添加兩個重要的配置源,systemProperties和systemEnvironment。

systemProperties對應System.getProperties(),即所有的系統屬性:

systemEnvironment對應的是System.getenv(),即系統的所有環境變量

(二)對Environment進行其他配置

? ? ?

??????? (1)首先添加conversionService:environment中的propertyResolver(配置解析器)配置應用轉換服務,例如NumberToNumberConverterFactory,StringToCharacterConverter等。應該是為propertyResource中的數據解析時進行數據轉換用的

? ? ? ? (2)configurePropertySources:

? ? ? ? 如果SpringApplication中Map<String, Object> defaultProperties不為空,則會創建一個名為“defaultProperties”,實例類型為DefaultPropertiesPropertySource的配置源。

????????java進程傳入的命令行參數加載進配置源中,配置源名稱為commandLineArgs,實例類型為CommandLinePropertySource。此方法為模板方法,可被子類覆蓋實現自己的資源加載方式configureProfiles

? ? ? ? (3)此為空實現,看注釋是說配置此應用程序環境中哪些配置文件處于活動狀態(或默認情況下處于活動狀態)。在配置文件處理過程中,可以通過{@code-spring.profiles.active}屬性激活其他配置文件。

(三)綁定ConfigurationPropertySources

ConfigurationPropertySources.attach(environment);

增加一個名為“configurationProperties”的ConfigurationPropertySourcesPropertySource和environment綁定,實際上是把environment中所有的propertySource(也包括configurationProperties)包裝進一個SpringConfigurationPropertySources實例中,而SpringConfigurationPropertySources是ConfigurationPropertySourcesPropertySource中的一個屬性值,這也意味著configurationProperties可以訪問所有的propertySource,這樣它可以作為配置的統一訪問入口。可以看如下configurationProperties對應實例屬性

所以ConfigurationPropertySourcesPropertySource.getProperty(String name),實際上就是遍歷每個PropertySource,獲取它們的配置,但它對每個PropertySource進行了適配,以便以統一的接口進行獲取配置。

getSource獲取的是SpringConfigurationPropertySources,是一個迭代器,iterator()中會對配置源進行適配,適配成ConfigurationPropertySource

(四)發布environmentPrepared事件

事件的發布流程都差不多,這里不再贅述。主要差別是哪些監聽器會監聽了此事件,并做了什么邏輯處理。這里我們重點說一下這個:

主要有6個監聽器:

代理監聽器可以跳過,沒有實際的邏輯處理。我們關注spring boot自定義的監聽器。

(1)EnvironmentPostProcessorApplicationListener

這里主要是從spring.fatories獲取EnvironmentPostProcessor接口實現類并實例化:

然后調用對應postProcessEnvironment,這些EnvironmentPostProcessor主要是添加不同的數據源配置,如ConfigDataEnvironmentPostProcessor解析我們常用的application.yml作為配置源,詳情可看《Spring boot源碼之EnvironmentPostProcessor》

(2)AnsiOutputApplicationListener

這里主要是根據spring.output.ansi.enabled和spring.output.ansi.console-available,設置AnsiOutput對應的屬性。為輸出到控制臺的日志信息添加 ANSI 轉義碼,以實現彩色輸出。這個用的比較少,我看只在打印banner和logback日志的顏色轉換器中用到了

(3)LoggingApplicationListener

在上一篇發布starting事件中,日志系統進行了初步初始化,在這里則會完成全部的初始化。

a、getLoggingSystemProperties(environment).apply():會將配置文件中配置的日志相關配置設置到系統屬性中,以便后續日志系統初始化時可以從系統屬性讀取。

如:配置文件中如果設置了logging.pattern.console,那么就會設置到系統屬性變量CONSOLE_LOG_PATTERN中。這里還設置了PID以及下面的日志策略

b、initializeEarlyLoggingLevel(environment):初始化早期日志級別,實際只是根據Environment中是否配置debug和trace,設置springBootLogging對應級別

c、initializeSystem(environment, this.loggingSystem, this.logFile):這里是主要的初始化邏輯,如果之前日志已經初始化過,這里會使用spring boot會重新初始化,對日志進行增強。比如在logback中,會使用SpringBootJoranConfigurator,對配置文件進行加載解析,同時新定義了一些解析規則

所以在spring boot中可以使用springProperty,添加屬性,值可以是Environment中配置的屬性值

如上,是配置了一個pid變量,值是Environment中pid屬性對應的屬性值

d、initializeFinalLoggingLevels(environment, this.loggingSystem):初始化日志的最終的日志級別:

如果b步驟設置了springBootLogging,那么spring boot會初始化一些logger,設置其日志級別,如過是debug級別,則下圖圈出來的都會設置是debug級別

另外則是對配置屬性中有logging.level為前綴的設置其對應的日志級別:

如上,則會設置com.example為true。

e、registerShutdownHookIfNecessary(environment, this.loggingSystem)

往SpringApplication注冊日志系統的shutdownHandler,會在shutdown發生時,停止日志上下文。

(4)BackgroundPreinitializer

啟動一個后臺線程去出發早期的初始化,并且有個countDownLatch,只有初始化完成,當ApplicationReadyEvent監聽觸發時,得等線程執行完才會繼續執行,否則等待

(5)FileEncodingApplicationListener

????????當系統設置了spring.mandatory-file-encoding編碼格式時,會判斷是否和System.getProperty("file.encoding")相同,如果不相等則拋出異常阻止系統的啟動,默認沒設置不影響

(五)其他

上面基本已經把環境變量準備完畢,剩下的是一些細微處理:

(1)將defaultProperties配置源移到最后,即查詢資源時最后才查它

(2)SpringApplication相關環境變量綁定

即將spring.main開頭的配置,綁定到對應SpringApplication的屬性中。如spring.main.allow-circular-references=true,那么就會設置SpringApplication的allowCircularReferences值為true.

(3)Environment轉換ConfigurableEnvironment為應用類型的環境,這里是ApplicationServletEnvironment,是ConfigurableEnvironment的子類,不需要轉換

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

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

相關文章

springmvc前端傳參,后端接收

RequestMapping注解 Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Mapping public interface RequestMapping {String name() default "";AliasFor("path")String[] value() default {};AliasFor(&quo…

分布式鎖 Redis vs etcd

為什么要實現分布式鎖?為什么需要分布式鎖,分布式鎖的作用是什么,哪些場景會使用到分布式鎖?分布式鎖的實現方式有哪些分布式鎖的核心原理是什么 如何實現分布式鎖redis(自旋鎖版本)etcd 的分布式鎖(互斥鎖(信號控制)版本) 分布式鎖對比redis vs etcd 總結 為什么要實現分布式…

【Excel/WPS】根據平均值,生成兩列/多列指定范圍的隨機數/隨機湊出兩列數據

原理就是通過隨機生成函數和平均值函數。 適用場景&#xff1a;在總體打分后&#xff0c;需要在小項中隨機生成小分數 第一列&#xff1a;固定的平均值A2第二列&#xff1a; RANDBETWEEN(A2-10,A210)第三列&#xff1a;根據第二列用平均值函數算除 A2*2-B2這是隨機值1的公式&am…

芯片詳細講解,從而區分CPU、MPU、DSP、GPU、FPGA、MCU、SOC、ECU

目錄 芯片的概念結構 芯片的派系劃分 通用芯片&#xff08;CPU&#xff0c;MPU&#xff0c;GPU&#xff0c;DSP&#xff09; 定制芯片&#xff08;FPGA&#xff0c;ASIC&#xff09; 芯片之上的集成&#xff08;MCU&#xff0c;SOC&#xff0c;ECU&#xff09; 軟硬件的匹…

運動相機拍攝的視頻打不開怎么辦

3-10 GoPro和大疆DJI運動相機的特點&#xff0c;小巧、高清、續航長、拍攝穩定&#xff0c;很多人會在一些重要場合用來拍攝視頻&#xff0c;比如可以用來拿在手里拍攝快速運動中的人等等。 但是畢竟是電子產品&#xff0c;有時候是會出點問題的&#xff0c;比如意外斷電、摔重…

智能化文檔開發(DI)

這個文檔涉及到多模態&#xff08;文本、發票、訂單、語音&#xff09; 對于普通的文本&#xff0c;我們希望對某些實體的某些屬性挖空生成文檔模版&#xff0c;并根據預設字段填空最后生成正式文件對于發票、訂單&#xff0c;我們想提取它的字段信息&#xff0c;寫入DB對于一些…

CSS語言的編程范式

CSS語言的編程范式 引言 在現代網頁開發中&#xff0c;CSS&#xff08;層疊樣式表&#xff09;作為一種樣式語言&#xff0c;承擔著網站前端呈現的重要角色。無論是簡單的靜態網頁還是復雜的單頁應用&#xff0c;CSS都在人機交互中發揮著至關重要的作用。掩蓋在美觀背后的&am…

【輕松學C:編程小白的大冒險】--- C語言簡介 02

在編程的藝術世界里&#xff0c;代碼和靈感需要尋找到最佳的交融點&#xff0c;才能打造出令人為之驚嘆的作品。而在這座秋知葉i博客的殿堂里&#xff0c;我們將共同追尋這種完美結合&#xff0c;為未來的世界留下屬于我們的獨特印記。 【輕松學C&#xff1a;編程小白的大冒險】…

零基礎 監控數據可視化 Spring Boot 2.x(Actuator + Prometheus + Grafana手把手) (上)

一、安裝Prometheus Releases prometheus/prometheus GitHubhttps://github.com/prometheus/prometheus/releases 或 https://prometheus.io/download/https://prometheus.io/download/ 1. 下載適用于 Windows 的二進制文件&#xff1a; 找到最新版本的發布頁面&#xf…

Idea日志亂碼

問題描述 前提&#xff1a;本人使用windows Idea運行sh文件&#xff0c;指定了utf-8編碼&#xff0c;但是運行過程中還是存在中文亂碼 Idea的相關配置都已經調整 字體調整為雅黑 文件編碼均調整為UTF-8 調整Idea配置文件 但是還是存在亂碼&#xff0c;既然Idea相關配置已經…

Linux 注冊線程化的中斷處理程序

1. 注冊線程化中斷處理函數 devmem_request_threaded_irq 是 Linux 內核中的一個函數&#xff0c;用于請求并注冊一個線程化的中斷處理程序。這個函數允許開發者注冊一個中斷處理函數&#xff0c;這個函數會在中斷發生時被調用&#xff0c;從而實現相應的中斷處理邏輯。它通過…

MySQL 數據表與索引設計藝術:打造高效數據存取架構

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《MySQL技術精粹》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、什么是MySQL 2、MySQL適用場景 二、MySQL的數據存儲與檢索 1、數據表…

安卓硬件加速hwui

安卓硬件加速 本文基于安卓11。 從 Android 3.0 (API 級別 11) 開始&#xff0c;Android 2D 渲染管道支持硬件加速&#xff0c;這意味著在 View 的畫布上執行的所有繪圖操作都使用 GPU。由于啟用硬件加速所需的資源增加&#xff0c;你的應用程序將消耗更多內存。 軟件繪制&am…

海信116英寸RGB-Mini LED:一朵綻放在科技穹頂的中國花火

東方古鎮的打鐵花&#xff0c;拉斯維加斯的煙花秀&#xff0c;盛大的花火表演總會在歲末年初的時候&#xff0c;吸引世界各地人們的目光。一年一度的科技展會&#xff0c;也起到煙花秀一樣的作用&#xff0c;讓人們提前望見未知的精彩。 CES還沒開始&#xff0c;CES 2025展會的…

超簡單,使用Kube-Vip實現K8s高可用VIP詳細教程

具體步驟如下&#xff1a; 以下步驟在其中一個 master 上操作即可&#xff0c; 1、參數配置 export VIP192.168.0.110 export INTERFACEens33 export KVVERSIONv0.8.7VIP 是虛擬IP地址&#xff0c;和主機同一個網段&#xff0c;且未被占用。INTERFACE 是你當前主機的網絡接口…

積分漏斗模型中5個指標統計

緣起 最近遇到一個積分漏斗模型的設計&#xff0c;這里記錄一下。以防止以后忘記了。其中畢竟關鍵的屬性是&#xff1a; 獲得積分可用積分已有積分 積分漏斗模型 這里隨著【當前日期】也就是今天日期。隨著時間一天天過去&#xff0c;積分也一天天過去。上面那個【填報時間】…

Ubuntu掛載Windows 磁盤,雙系統

首先我們需要在終端輸入這個命令&#xff0c;來查看磁盤分配情況 lsblk -f 找到需要掛載的磁盤&#xff0c;檢查其類型&#xff08; 我的/dev/nvme2n1p1類型是ntfs&#xff0c;名字叫3500winData&#xff09; 然后新建一個掛載磁盤的目錄&#xff0c;我的是/media/zeqi/3500wi…

程序血緣分析技術在工商銀行軟件工程中的應用

當前,隨著軟件領域技術更新換代速度的日益加快,市場需求也變得更加多樣化和個性化,業界普遍通過加速產品迭代來滿足客戶需求,但在此過程中也暴露出一些研發管理痛點問題,如服務和程序類資產信息分散于各個不同的應用和系統中,信息歸集費時費力;設計、開發和測試人員無法…

微信小程序中 隱藏scroll-view 滾動條 網頁中隱藏滾動條

在微信小程序中隱藏scroll-view的滾動條可以通過以下幾種方法實現&#xff1a; 方法一&#xff1a;使用CSS隱藏滾動條 在小程序的樣式文件中&#xff08;如app.wxss或頁面的.wxss文件&#xff09;&#xff0c;添加以下CSS代碼來隱藏滾動條&#xff1a; scroll-view ::-webkit…

服務器證書不受信任是什么問題?

用戶在訪問某些網站時&#xff0c;可能會遇到“服務器證書不受信任”的警告。這一問題不僅影響用戶的瀏覽體驗&#xff0c;更可能對網站的信譽和安全性產生深遠影響。那么服務器證書不受信任是什么問題呢&#xff1f; 服務器證書的基本概念 服務器證書是由證書頒發機構(CA)簽…