精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

18張圖,詳解 SpringBoot 解析 Yml 全流程

開發 架構
當我們啟動一個SpringBoot程序,在執行SpringApplication.run()的時候,首先在初始化SpringApplication的過程中,加載了11個實現了ApplicationListener接口的攔截器。

背景

前幾天的時候,項目里有一個需求,需要一個開關控制代碼中是否執行一段邏輯,于是理所當然的在yml文件中配置了一個屬性作為開關,再配合nacos就可以隨時改變這個值達到我們的目的,yml文件中是這樣寫的:

  1. switch: 
  2.   turnOn: on 

程序中的代碼也很簡單,大致的邏輯就是下面這樣,如果取到的開關字段是on的話,那么就執行if判斷中的代碼,否則就不執行:

  1. @Value("${switch.turnOn}"
  2. private String on
  3.  
  4. @GetMapping("testn"
  5. public void test(){ 
  6.     if ("on".equals(on)){ 
  7.         //TODO 
  8.     } 

但是當代碼實際跑起來,有意思的地方來了,我們發現判斷中的代碼一直不會被執行,直到debug一下,才發現這里的取到的值居然不是on而是true。

看到這,是不是感覺有點意思,首先盲猜是在解析yml的過程中把on作為一個特殊的值進行了處理,于是我干脆再多測試了幾個例子,把yml中的屬性擴展到下面這些:

  1. switch: 
  2.   turnOn: on 
  3.   turnOff: off 
  4.   turnOn2: 'on' 
  5.   turnOff2: 'off' 

再執行一下代碼,看一下映射后的值:

可以看到,yml中沒有帶引號的on和off被轉換成了true和false,帶引號的則保持了原來的值不發生改變。

到這里,讓我忍不住有點好奇,為什么會發生這種現象呢?于是強忍著困意翻了翻源碼,硬磕了一下SpringBoot加載yml配置文件的過程,終于讓我看出了點門道,下面我們一點一點細說!

因為配置文件的加載會涉及到一些SpringBoot啟動的相關知識,所以如果對這一塊不是很熟悉的同學,可以先提前先看一下Hydra在古早時期寫過一篇文章預熱一下。下面的介紹中,只會摘出一些對加載和解析配置文件比較重要的步驟進行分析,對其他無關部分進行了省略。

加載監聽器

當我們啟動一個SpringBoot程序,在執行SpringApplication.run()的時候,首先在初始化SpringApplication的過程中,加載了11個實現了ApplicationListener接口的攔截器。

這11個自動加載的ApplicationListener,是在spring.factories中定義并通過SPI擴展被加載的:

這里列出的10個是在spring-boot中加載的,還有剩余的1個是在spring-boot-autoconfigure中加載的。其中最關鍵的就是ConfigFileApplicationListener,它和后面要講到的配置文件的加載相關。

執行run方法

在實例化完成SpringApplication后,會接著往下執行它的run方法。

可以看到,這里通過getRunListeners方法獲取的SpringApplicationRunListeners中,EventPublishingRunListener綁定了我們前面加載的11個監聽器。但是在執行starting方法時,根據類型進行了過濾,最終實際只執行了4個監聽器的onApplicationEvent方法,并沒有我們希望看到的ConfigFileApplicationListener,讓我們接著往下看。

當run方法執行到prepareEnvironment時,會創建一個ApplicationEnvironmentPreparedEvent類型的事件,并廣播出去。這時所有的監聽器中,有7個會監聽到這個事件,之后會分別調用它們的onApplicationEvent方法,其中就有了我們心心念念的ConfigFileApplicationListener,接下來讓我們看看它的onApplicationEvent方法中做了什么。

在方法的調用過程中,會加載系統自己的4個后置處理器以及ConfigFileApplicationListener自身,一共5個后置處理器,并執行他們的postProcessEnvironment方法,其他4個對我們不重要可以略過,最終比較關鍵的步驟是創建Loader實例并調用它的load方法。

加載配置文件

這里的Loader是ConfigFileApplicationListener的一個內部類,看一下Loader對象實例化的過程:

在實例化Loader對象的過程中,再次通過SPI擴展的方式加載了兩個屬性文件加載器,其中的YamlPropertySourceLoader就和后面的yml文件的加載、解析密切關聯,而另一個PropertiesPropertySourceLoader則負責properties文件的加載。創建完Loader實例后,接下來會調用它的load方法。

在load方法中,會通過嵌套循環方式遍歷默認配置文件存放路徑,再加上默認的配置文件名稱、以及不同配置文件加載器對應解析的后綴名,最終找到我們的yml配置文件。接下來,開始執行loadForFileExtension方法。

在loadForFileExtension方法中,首先將classpath:/application.yml加載為Resource文件,接下來準備正式開始,調用了之前創建好的YamlPropertySourceLoader對象的load方法。

封裝Node

在load方法中,開始準備進行配置文件的解析與數據封裝:

load方法中調用了OriginTrackedYmlLoader對象的load方法,從字面意思上我們也可以理解,它的用途是原始追蹤yml的加載器。中間一連串的方法調用可以忽略,直接看最后也是最重要的是一步,調用OriginTrackingConstructor對象的getData接口,來解析yml并封裝成對象。

在解析yml的過程中實際使用了Composer構建器來生成節點,在它的getNode方法中,通過解析器事件來創建節點。通常來說,它會將yml中的一組數據封裝成一個MappingNode節點,它的內部實際上是一個NodeTuple組成的List,NodeTuple和Map的結構類似,由一對對應的keyNode和valueNode構成,結構如下:

好了,讓我們再回到上面的那張方法調用流程圖,它是根據文章開頭的yml文件中實際內容內容繪制的,如果內容不同調用流程會發生改變,大家只需要明白這個原理,下面我們具體分析。

首先,創建一個MappingNode節點,并將switch封裝成keyNode,然后再創建一個MappingNode,作為外層MappingNode的valueNode,同時存儲它下面的4組屬性,這也是為什么上面會出現4次循環的原因。如果有點困惑也沒關系,看一下下面的這張圖,就能一目了然了解它的結構。

在上圖中,又引入了一種新的ScalarNode節點,它的用途也比較簡單,簡單String類型的字符串用它來封裝成節點就可以了。到這里,yml中的數據被解析完成并完成了初步的封裝,可能眼尖的小伙伴要問了,上面這張圖中為什么在ScalarNode中,除了value還有一個tag屬性,這個屬性是干什么的呢?

在介紹它的作用前,先說一下它是怎么被確定的。這一塊的邏輯比較復雜,大家可以翻一下ScannerImpl類fetchMoreTokens方法的源碼,這個方法會根據yml中每一個key或value是以什么開頭,來決定以什么方式進行解析,其中就包括了{、[、'、%、?等特殊符號的情況。以解析不帶任何特殊字符的字符串為例,簡要的流程如下,省略了一些不重要部分:

在這張圖的中間步驟中,創建了兩個比較重要的對象ScalarToken和ScalarEvent,其中都有一個為true的plain屬性,可以理解為這個屬性是否需要解釋,是后面獲取Resolver的關鍵屬性之一。

上圖中的yamlImplicitResolvers其實是一個提前緩存好的HashMap,已經提前存儲好了一些Char類型字符與ResolverTuple的對應關系:

當解析到屬性on時,取出首字母o對應的ResolverTuple,其中的tag就是tag:yaml.org.2002:bool。當然了,這里也不是簡單的取出就完事了,后續還會對屬性進行正則表達式的匹配,看與regexp中的值是否能對的上,檢查無誤時才會返回這個tag。

到這里,我們就解釋清楚了ScalarNode中tag屬性究竟是怎么獲取到的了,之后方法調用層層返回,返回到OriginTrackingConstructor父類BaseConstructor的getData方法中。接下來,繼續執行constructDocument方法,完成對yml文檔的解析。

調用構造器

在constructDocument中,有兩步比較重要,第一步是推斷當前節點應該使用哪種類型的構造器,第二步是使用獲得的構造器來重新對Node節點中的value進行賦值,簡易流程如下,省去了循環遍歷的部分:

推斷構造器種類的過程也很簡單,在父類BaseConstructor中,緩存了一個HashMap,存放了節點的tag類型到對應構造器的映射關系。在getConstructor方法中,就使用之前節點中存入的tag屬性來獲得具體要使用的構造器:

當tag為bool類型時,會找到SafeConstruct中的內部類 ConstructYamlBool作為構造器,并調用它的construct方法實例化一個對象,來作為ScalarNode節點的value的值:

在construct方法中,取到的val就是之前的on,至于下面的這個BOOL_VALUES,也是提前初始化好的一個HashMap,里面提前存放了一些對應的映射關系,key是下面列出的這些關鍵字,value則是Boolean類型的true或false:

到這里,yml中的屬性解析流程就基本完成了,我們也明白了為什么yml中的on會被轉化為true的原理了。

思考

那么,下一個問題來了,既然yml文件解析中會做這樣的特殊處理,那么如果換成properties配置文件怎么樣呢?

  1. sw.turnOn=on 
  2. sw.turnOff=off 

執行一下程序,看一下結果:

可以看到,使用properties配置文件能夠正常讀取結果,看來是在解析的過程中沒有做特殊處理,至于解析的過程,有興趣的小伙伴可以自己去閱讀一下源碼。

那么,今天就寫到這里,我們下期見。

本文轉載自微信公眾號「碼農參上」,可以通過以下二維碼關注。轉載本文請聯系碼農參上公眾號。

 

責任編輯:武曉燕 來源: 碼農參上
相關推薦

2022-01-14 14:50:14

SpringBootymlJava

2025-05-28 08:35:00

Nacos服務訂閱流程開發

2025-06-03 08:25:00

Nacos開發服務

2025-06-04 04:00:00

Spring掃碼登錄免密認證

2022-07-27 09:53:06

神經網絡結構

2025-06-09 07:11:56

2018-11-28 15:15:52

大數據AI安防

2015-06-24 10:51:10

iOS學習流程

2022-03-18 13:58:00

RocketMQ消息隊列

2021-09-29 11:30:01

大數據技術架構

2021-06-16 17:45:24

javaMESA模型

2025-07-02 08:10:01

StarRocks物化視圖MV

2021-04-19 07:57:23

Spring 源碼GetBean

2024-03-18 07:48:00

大語言模型NVIDIA生成式 AI

2021-04-23 10:55:52

人工智能深度學習

2024-08-07 08:19:13

2025-06-26 02:11:00

2025-02-10 14:13:54

SQL語句query

2022-09-26 11:32:14

用戶分層服務業務

2021-03-18 12:16:44

用戶分層業務
點贊
收藏

51CTO技術棧公眾號

久久影视中文字幕| 日本性高潮视频| 日韩在线伦理| 中文一区一区三区高中清不卡| 成人网中文字幕| 成人免费看片98欧美| 日韩欧美网站| 亚洲国产私拍精品国模在线观看| 日本免费观看网站| 牛牛电影国产一区二区| 国产欧美一区二区精品性色| 91成人伦理在线电影| 无码人妻精品一区二区三区不卡| 婷婷综合网站| 亚洲欧美一区二区三区久久| 91香蕉视频免费看| 成人mm视频在线观看| 亚洲宅男天堂在线观看无病毒| 午夜视频久久久| 天堂av中文字幕| 国产一区二区三区高清播放| 日韩免费av片在线观看| 九九热精品在线观看| 日韩久久综合| 亚洲乱亚洲乱妇无码| 国产精品日日摸夜夜爽| 99久久久成人国产精品| 日本精品一区二区三区高清 | 香蕉加勒比综合久久| 视频一区视频二区视频三区高| 免费观看黄色一级视频| 韩国精品一区二区| 国产精品免费电影| 久久久精品毛片| 亚洲综合国产| 韩国视频理论视频久久| 国产亚洲精品成人| 欧美国产免费| 欧美另类极品videosbest最新版本| 人妻熟人中文字幕一区二区| 久草精品在线| 亚洲开心激情网| 中文字幕免费高清视频| 99精品国产高清一区二区麻豆| 宅男噜噜噜66一区二区66| 亚洲国产日韩欧美在线观看| 日韩成人亚洲| 欧洲另类一二三四区| 一本久道中文无码字幕av| 中文不卡1区2区3区| 污片在线观看一区二区| 黄色成人在线看| zzzwww在线看片免费| 亚洲成人免费电影| 久久久久免费看黄a片app| 波多野在线观看| 亚洲成人一二三| 日韩中文字幕在线免费| 91黄页在线观看| 精品成人在线视频| 精品国产成人av在线免| 蜜桃精品在线| 欧美日韩日日夜夜| 亚洲另类第一页| 9999在线精品视频| 91精品国产欧美日韩| xxxx视频在线观看| 久久精品凹凸全集| 精品亚洲一区二区三区四区五区| 97伦伦午夜电影理伦片| 精品国产一区二区三区小蝌蚪 | 免费在线观看一区二区三区| 国产精品自拍小视频| 国产精品久久久久久在线| 国产精品一区二区91| 国产乱码精品一区二区三区日韩精品 | 成人看av片| 亚洲成人手机在线| www黄色av| 色诱色偷偷久久综合| 日韩精品专区在线| 熟女丰满老熟女熟妇| jiujiure精品视频播放| 久久久精品国产| 国产无遮挡又黄又爽| 久久激情中文| 成人在线精品视频| 日本韩国在线观看| 国产精品午夜在线观看| 少妇久久久久久被弄到高潮| 亚洲欧美韩国| 日韩一级黄色大片| 三级网站在线免费观看| gogogo高清在线观看一区二区| 久久99青青精品免费观看| 影音先锋亚洲天堂| 国内一区二区在线| 久久精品一二三区| av网站在线免费看推荐| 日韩欧美国产骚| 久久久久久久久久毛片| 一区二区三区日本久久久| 久久影院在线观看| 不卡av电影在线| 国产成人免费视频一区| 婷婷四月色综合| 91白丝在线| 制服丝袜亚洲精品中文字幕| 最新中文字幕视频| 欧美日本二区| 国产日韩欧美91| 亚洲欧美综合在线观看| 亚洲欧美激情一区二区| 国产 porn| 亚洲三级网址| 国内精品久久久久久中文字幕 | 麻豆精品精品国产自在97香蕉| 国产精品日本一区二区| 国产黄色小视频在线| 91高清视频在线| 在线观看国产免费视频| 欧美在线资源| 国产精品麻豆va在线播放| 亚洲欧美色视频| 午夜久久久影院| 国产一级片中文字幕| 久久电影院7| 国产精品福利网站| 日韩偷拍自拍| 天天综合色天天综合| 亚洲一级Av无码毛片久久精品| 四虎8848精品成人免费网站| 国产v综合ⅴ日韩v欧美大片| 天天av天天翘| 午夜久久久久久久久久一区二区| 黑人巨大猛交丰满少妇| 91精品二区| 国产综合视频在线观看| yjizz视频网站在线播放| 色悠久久久久综合欧美99| 亚洲av网址在线| 亚洲一区二区三区四区五区午夜 | 亚洲欧洲中文字幕| 国产日韩中文字幕在线| 免费观看久久久久| 欧美日韩免费不卡视频一区二区三区 | 日本人成精品视频在线| 日本大片在线观看| 狠狠色狠狠色综合日日五| 亚洲天堂网一区二区| 国产精品久久777777毛茸茸| 久久精品日产第一区二区三区| 免费毛片b在线观看| 日韩精品久久久久久久玫瑰园| 日产精品久久久久| 99久久精品国产观看| 欧美牲交a欧美牲交aⅴ免费真 | 国产suv精品一区二区6| 久久这里只有精品8| 国产精品一线| 欧美在线性视频| 在线免费观看黄| 欧美精品一卡二卡| 亚洲成人生活片| 成人一级视频在线观看| 国产女大学生av| 欧美军人男男激情gay| 国产日韩av在线| 欧美1234区| 亚洲精品中文字幕女同| 久久久久久av无码免费看大片| 国产精品高清亚洲| av在线天堂网| 亚洲欧美日韩国产一区| 亚洲精品一卡二卡三卡四卡| 国产精品视频一区二区三区| 欧美极品少妇全裸体| 亚洲欧美一区二区三| 欧美日韩一区视频| 青青草精品在线视频| 99久久精品免费看国产| 日本免费观看网站| 欧美日韩国产免费观看| 欧美日韩精品一区| 日韩av综合| 国产精品成熟老女人| 中文字幕在线观看网站| 日韩国产精品亚洲а∨天堂免| 这里只有久久精品视频| 一区二区在线观看不卡| 91玉足脚交白嫩脚丫| 理论电影国产精品| 免费看又黄又无码的网站| 99国产精品一区二区| 激情五月综合色婷婷一区二区| www.一区| 2020久久国产精品| 菠萝菠萝蜜在线视频免费观看| 亚洲精品国产精品国产自| 96日本xxxxxⅹxxx17| 欧美日韩另类在线| 免费在线观看h片| 久久久精品综合| 亚洲午夜久久久久久久久| 免费久久精品视频| 国产 日韩 亚洲 欧美| 99精品小视频| 欧美一区二区视频17c| 视频亚洲一区二区| 国产日韩在线观看av| 暖暖成人免费视频| 久久免费精品视频| 成年人网站在线| 在线看国产精品| 香蕉视频免费看| 日韩免费电影网站| 亚洲天堂网在线观看视频| 日韩欧美在线中文字幕| 国产亚洲精品久久久久久无几年桃 | 一级片一级片一级片| 日韩一级在线播放| 国产成人av一区二区三区在线| 欧美牲交a欧美牲交aⅴ免费下载| 欧美精品色网| 手机福利在线视频| 日本a级不卡| 欧美高清视频一区| 久久久久久毛片免费看 | 亚洲国产精品久久久久婷蜜芽| 欧美日韩视频一区二区三区| 黑人巨大国产9丨视频| 91视频久久| 中文字幕不卡每日更新1区2区| 国产免费久久| 欧美三日本三级少妇三99| 久久丝袜视频| 精品久久久久久中文字幕动漫| 哺乳一区二区三区中文视频| 99一区二区三区| 欧美大片91| 97人人干人人| 中文字幕日韩在线| av一区和二区| 国产在线播放精品| 国产视频在线观看一区| 久久97精品| 精品视频导航| 精品一区亚洲| 亚洲精品日韩精品| 天天做天天爱天天综合网| 色中文字幕在线观看| 91精品国产乱码久久久久久久 | 激情五月综合色婷婷一区二区| 激情亚洲另类图片区小说区| 国产三级精品在线不卡| 国内露脸中年夫妇交换精品| 精品视频第一区| 精品一区二区三区在线| 亚洲国产另类久久久精品极度| 久久精品国产68国产精品亚洲| 男同互操gay射视频在线看| 亚洲成av人片乱码色午夜| japanese在线播放| 精品av久久久久电影| 97xxxxx| 美腿丝袜亚洲色图| 午夜激情视频网| k8久久久一区二区三区| 亚洲熟妇无码av| 1区2区3区欧美| 国产精品7777777| 色视频一区二区| 97久久人国产精品婷婷| 精品国产乱码久久久久久久久| 视频国产在线观看| 国产一区二区三区直播精品电影 | 国产一区日韩| 免费观看中文字幕| 一本一道久久综合狠狠老精东影业| 久久精品一区二| 久久黄色级2电影| 丰满少妇xbxb毛片日本| 国产欧美精品一区二区色综合| 国产人妻精品一区二区三区不卡| 亚洲444eee在线观看| 日本一区二区三区久久| 精品国产一区二区三区久久久蜜月| 亚洲欧洲综合在线| 超碰91人人草人人干| 电影一区二区三| 91成人免费视频| 精品免费视频| 黄色成人在线看| 国产一区欧美一区| 18禁裸乳无遮挡啪啪无码免费| 亚洲精选在线视频| 91在线视频免费播放| 精品剧情在线观看| 中文字幕日本在线| 68精品国产免费久久久久久婷婷| 亚洲国产伊人| 日本在线播放一区| 亚洲激情自拍| 一级黄色在线播放| 日本一区二区免费在线观看视频 | 在线电影一区| 中文字幕视频三区| 久久九九全国免费| 日本三级理论片| 日韩一区二区三区免费看| 久久经典视频| 欧美性在线观看| 风间由美一区二区av101| 波多野结衣三级在线| 爽好多水快深点欧美视频| 欧美做受高潮中文字幕| 亚洲精品乱码久久久久| 在线免费观看中文字幕| 亚洲男人天堂2019| 蜜桃av.网站在线观看| 成人9ⅰ免费影视网站| 999国产精品999久久久久久| 欧美精品成人网| 久久久久久夜精品精品免费| 日产欧产va高清| 亚洲白虎美女被爆操| 污污视频在线| 91精品天堂| 欧美有码视频| 手机在线免费毛片| 亚洲人午夜精品天堂一二香蕉| 国产一区二区女内射| 少妇精69xxtheporn| 日韩一区二区三区在线免费观看 | 狠狠干综合网| avtt中文字幕| 亚洲国产婷婷综合在线精品| 国内毛片毛片毛片毛片| 蜜臀久久99精品久久久无需会员| va天堂va亚洲va影视| 最新精品视频| 国产一区二区在线视频| 成人涩涩小片视频日本| 欧美一区二区三区爱爱| 成人在线免费看黄| 99在线高清视频在线播放| 国产精品草草| 星空大象在线观看免费播放| 精品国产老师黑色丝袜高跟鞋| 天堂在线中文字幕| 欧美在线视频一区| 成人嫩草影院| 国产精品久久a| 亚洲色图欧洲色图| 亚洲风情第一页| 久久免费视频在线| 尤物tv在线精品| 亚洲一二三区av| 亚洲欧美在线视频| 亚洲毛片欧洲毛片国产一品色| 国内外成人免费激情在线视频网站 | 久草在线资源站资源站| 国模一区二区三区私拍视频| 亚洲永久在线| 亚洲色图100p| 日韩视频免费观看高清完整版| heyzo高清在线| 日韩欧美视频一区二区三区四区| 老司机午夜精品99久久| 美国黄色小视频| 日韩精品亚洲元码| 国产原创一区| 日韩一级片免费视频| 久久综合久久鬼色中文字| 一本大道伊人av久久综合| 欧美激情视频给我| 亚洲区小说区| 下面一进一出好爽视频| 欧美三级免费观看| 欧美成人高清在线| 精品一区二区不卡| 久久国产精品一区二区| 精品无码m3u8在线观看| 亚洲日韩中文字幕| 精品国产一区二| 中文字幕乱码人妻综合二区三区| 欧美激情一区二区三区蜜桃视频| 国产女无套免费视频| 欧美孕妇与黑人孕交| 91九色精品国产一区二区| 182在线视频| 91精品国产综合久久久蜜臀图片| 欧亚av在线| 桥本有菜av在线| 久久久不卡网国产精品二区| 亚洲第一免费视频| 国产一区在线播放| 美女精品在线| 豆国产97在线 | 亚洲| 日韩在线播放视频|