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

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

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

 背景

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

  1. switch:  
  2.   turnOn: on 

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

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

但是當代碼實際跑起來,有意思的地方來了,我們發現判斷中的代碼一直不會被執行,直到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配置文件能夠正常讀取結果,看來是在解析的過程中沒有做特殊處理,至于解析的過程,有興趣的小伙伴可以自己去閱讀一下源碼。 

 

責任編輯:龐桂玉 來源: Java知音
相關推薦

2022-01-13 17:24:04

SpringBootYml監聽器

2025-05-28 08:35:00

Nacos服務訂閱流程開發

2025-06-03 08:25:00

Nacos開發服務

2025-06-04 04:00:00

Spring掃碼登錄免密認證

2025-06-09 07:11:56

2022-07-27 09:53:06

神經網絡結構

2015-06-24 10:51:10

iOS學習流程

2018-11-28 15:15:52

大數據AI安防

2022-03-18 13:58:00

RocketMQ消息隊列

2021-09-29 11:30:01

大數據技術架構

2021-06-16 17:45:24

javaMESA模型

2021-04-23 10:55:52

人工智能深度學習

2025-07-02 08:10:01

StarRocks物化視圖MV

2021-04-19 07:57:23

Spring 源碼GetBean

2024-03-18 07:48:00

大語言模型NVIDIA生成式 AI

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技術棧公眾號

精品国产亚洲在线| 中文字幕一区二区三区在线不卡| 久久久久久久国产精品| 精品伦一区二区三区| 国产丝袜精品丝袜| www激情久久| 国产精品视频专区| 久久久久99精品成人片毛片| 婷婷成人综合| 在线成人午夜影院| 国产主播自拍av| a√在线中文网新版址在线| 国产一区二区女| 国产91|九色| 国产极品国产极品| 国产伦精品一区二区三区视频| 51精品久久久久久久蜜臀| 怡红院av亚洲一区二区三区h| 超碰免费97在线观看| 成人在线综合网站| 国产日韩在线一区| 欧美精品一二三四区| 欧美日韩亚洲系列| 久久人91精品久久久久久不卡| 美国黄色一级毛片| 色妞ww精品视频7777| 91国模大尺度私拍在线视频| 91.com在线| 欧美日韩xx| 久久综合久久综合亚洲| 岛国一区二区三区高清视频| 依依成人在线视频| 久久狠狠一本精品综合网| 欧美伦理91i| 99久久99久久精品免费看小说.| 国产一区二区在线视频你懂的| 欧美丰满少妇xxxxx高潮对白| 久久久精品在线视频| www中文字幕在线观看| 亚洲图片激情小说| 杨幂一区欧美专区| 成人免费高清在线播放| 久久久精品蜜桃| 久精品国产欧美| 亚洲国产999| 国产一区二区三区免费看| 国产精品一区二区三区在线播放 | 久久久久久国产精品三级玉女聊斋 | 亚洲午夜无码久久久久| 免费亚洲婷婷| 日本sm极度另类视频| 日韩欧美一区二区一幕| 精品动漫3d一区二区三区免费版| 久久99亚洲精品| 天天看片中文字幕| 欧美日韩国产精品一区二区亚洲| 日韩中文字幕在线播放| 亚欧精品视频一区二区三区| 精品久久中文| 中文字幕日韩精品在线| 内射毛片内射国产夫妻| 日韩在线视频精品| 色yeye香蕉凹凸一区二区av| 182在线观看视频| 天天久久综合| 欧美日韩电影在线观看| 久久久久国产精品夜夜夜夜夜| 欧美日韩 国产精品| 久久深夜福利免费观看| 老妇女50岁三级| 在线成人欧美| 欧美与黑人午夜性猛交久久久| 国产成人精品av久久| 一区二区91| 国产精品18久久久久久首页狼| 高潮无码精品色欲av午夜福利| 麻豆精品一区二区| 9a蜜桃久久久久久免费| 欧美特级特黄aaaaaa在线看| 91在线免费视频观看| 天天人人精品| 在线网址91| 精品福利樱桃av导航| 冲田杏梨av在线| 国产精品白丝久久av网站| 精品国产电影一区二区 | 欧美国产日韩a欧美在线观看| 一区二区三区四区在线视频 | 久久人91精品久久久久久不卡| 秋霞精品一区二区三区| 精品一区在线看| 国产精品入口免费| 国产私人尤物无码不卡| 亚洲欧美国产高清| 日本久久久精品视频| 国产精品久久久久77777丨| 日韩一区二区三区高清免费看看| 天天插天天射天天干| 日韩免费视频| 久久欧美在线电影| 中文字幕在线观看免费| 成人爽a毛片一区二区免费| 日本一区免费观看| 四虎影视国产在线视频| 日本高清免费不卡视频| 女王人厕视频2ⅴk| 欧美日中文字幕| 高清欧美性猛交xxxx| 正在播放亚洲精品| av男人天堂一区| 中文字幕久精品免| 欧美男男tv网站在线播放| 在线播放中文一区| 美女洗澡无遮挡| 国产精品99一区二区| 国产精品极品在线| 神马午夜在线观看| 国产精品剧情在线亚洲| 国产男女无遮挡| 2020最新国产精品| 俺去了亚洲欧美日韩| 黄色av一级片| av一区二区三区在线| 三级在线免费观看| 国产精品美女午夜爽爽| 亚洲美女av电影| 不卡的免费av| 国产黄色成人av| 免费观看黄色大片| 国产精品久久久久久久久免费高清| 日韩av在线免费| 久久久久久久黄色| 国产麻豆一精品一av一免费 | 成人精品一区二区三区免费| 懂色av影视一区二区三区| 国产亚洲精品成人a| 这里只有精品在线| 成人信息集中地欧美| 懂色av中文在线| 日韩人体视频一二区| 黄色网址在线视频| 亚洲二区免费| 国产精品日韩一区二区| 丰满诱人av在线播放| 日韩午夜电影av| 人妻少妇精品一区二区三区| 国模无码大尺度一区二区三区| 亚洲精品一卡二卡三卡四卡| 色婷婷综合久久久中字幕精品久久| 亚洲精品456在线播放狼人| 久久黄色免费视频| 成人不卡免费av| 成人在线观看你懂的| 波多野结衣一区二区三区免费视频| 欧美日韩999| 丰满人妻av一区二区三区| 亚洲综合激情另类小说区| 中文字幕人妻熟女人妻a片| 欧美精品91| 国产精品污www一区二区三区| 国产精品一品| 国产午夜精品久久久| 亚洲不卡在线视频| 国产女同性恋一区二区| 精品久久久99| 欧美不卡视频| 国产美女在线精品免费观看| 啊啊啊久久久| 亚洲欧美日韩国产中文专区| 国产精华7777777| 中文字幕一区二区三区视频| 午夜影院免费版| 亚洲高清自拍| 欧美极品视频一区二区三区| 成人av色网站| 久久999免费视频| 日本高清中文字幕二区在线| 欧美色图在线观看| 青青草免费av| 久久在线观看免费| 欧美日韩中文不卡| 黄色成人av网站| 欧美成人第一区| 中文幕av一区二区三区佐山爱| 欧美黑人巨大精品一区二区| 日本午夜在线视频| 777色狠狠一区二区三区| 国产在线视频二区| 国产欧美日韩综合| 中文字幕在线观看91| 久久精品成人| 伊人久久在线观看| 国产精品最新| 97超碰人人模人人爽人人看| 五月天国产在线| 久久精品视频99| 色在线免费视频| 日韩一区二区免费在线电影| 色屁屁影院www国产高清麻豆| 亚洲欧洲美洲综合色网| 7788色淫网站小说| 国产主播一区二区三区| 人妻熟女一二三区夜夜爱| 亚州av乱码久久精品蜜桃 | 四虎国产精品永远| 777精品伊人久久久久大香线蕉| 日韩视频免费观看高清| 国产精品久久三区| 超碰97人人干| 成人在线一区二区三区| 91亚洲免费视频| 老司机一区二区三区| 国产精品三级一区二区| 成人aaaa| 欧美精品一区二区三区久久| 中文在线综合| 成人在线视频网站| 播放一区二区| 51精品国产黑色丝袜高跟鞋| www视频在线看| 中文字幕日韩欧美精品在线观看| 视频三区在线观看| 欧美第一区第二区| 国产女人高潮毛片| 欧美三级在线视频| 日日夜夜操视频| 欧美日韩激情网| 国产成年人免费视频| 一区二区三区中文字幕| 久久av红桃一区二区禁漫| 国产日韩欧美高清| 丰满少妇在线观看资源站| 成人网男人的天堂| 国产香蕉精品视频| 国产成人av电影在线观看| 久久成年人网站| 精品综合久久久久久8888| 另类小说第一页| 日本 国产 欧美色综合| 污污视频网站免费观看| 天堂资源在线中文精品| 四虎永久在线精品无码视频| 国产精品尤物| 日韩人妻精品无码一区二区三区| 亚洲精品四区| av免费观看网| 午夜在线观看免费一区| 亚洲自偷自拍熟女另类| 国产精品视频| 日日碰狠狠躁久久躁婷婷| 美女黄网久久| 天堂社区在线视频| 麻豆国产精品777777在线| 视频在线观看免费高清| 激情综合五月婷婷| 夜夜爽久久精品91| 成人av网站在线观看| 欧美大片免费播放器| 久久亚洲二区三区| 在线观看日本黄色| 亚洲欧美日本韩国| 精国产品一区二区三区a片| 一区二区三区精品| 日韩精品视频免费播放| 精品久久久久久亚洲精品| 91在线视频在线观看| 欧美综合色免费| 国产精品爽爽久久久久久| 欧美大片在线观看| 亚洲 欧美 激情 小说 另类| 亚洲天堂av在线播放| 日本福利在线| 色综合久综合久久综合久鬼88| 91豆花视频在线播放| 日本久久久久久久久久久| 成人18视频在线观看| 99九九视频| 国产成人ay| 欧美少妇一级片| 亚洲无毛电影| 十八禁视频网站在线观看| 久草中文综合在线| 久久久老熟女一区二区三区91| 久久亚洲综合色一区二区三区 | 亚洲国产一区二区三区| 六月丁香婷婷综合| 欧美日韩不卡视频| 色综合免费视频| 色偷偷噜噜噜亚洲男人| 福利小视频在线| 国产精品最新在线观看| 国产一区二区三区不卡av| 亚洲国产综合自拍| 最新亚洲激情| 91精产国品一二三产区别沈先生| 床上的激情91.| 国产精品18在线| 午夜影视日本亚洲欧洲精品| 日本成人一级片| 精品处破学生在线二十三| 国产黄在线观看| 性欧美xxxx交| 国产精品一级在线观看| 欧美日韩在线一区二区三区| 欧美日韩国产一区精品一区| 日韩欧美在线免费观看视频| 懂色av一区二区三区免费观看| 国产123在线| 无码av中文一区二区三区桃花岛| 夜夜躁很很躁日日躁麻豆| 日韩电影大片中文字幕| 黄网站在线播放| 国产成人精品免费视频| 国产精品2023| 亚洲区成人777777精品| 日本在线不卡视频| 亚洲熟女乱综合一区二区三区| 亚洲欧美怡红院| 日批视频免费观看| 亚洲人成电影网站色xx| 九九色在线视频| 成人欧美一区二区三区黑人孕妇| 曰本一区二区三区视频| 欧美午夜性视频| 丁香桃色午夜亚洲一区二区三区| 成年人视频软件| 欧美在线视频你懂得| 亚洲 另类 春色 国产| 久久久欧美一区二区| 人人九九精品视频| 自拍亚洲欧美老师丝袜| 青娱乐精品视频| 波多野结衣片子| 欧美日韩国产在线| 天天射天天色天天干| 久久久久国产精品一区| 视频一区中文字幕精品| 超碰免费在线公开| 久久99蜜桃精品| 影音先锋男人资源在线观看| 欧美在线观看视频在线| 成a人片在线观看www视频| 国产精品吹潮在线观看| 精品国产视频| 黑森林精品导航| 国产精品免费视频网站| 在线观看免费视频一区| 中文字幕欧美日韩精品| 日韩色性视频| 日本福利视频导航| 国产成人亚洲综合a∨婷婷图片| 中文字幕av久久爽av| 日韩欧美国产综合一区| 成人免费一区二区三区牛牛| 国产在线精品日韩| 亚洲一区二区伦理| 法国空姐电影在线观看| 欧美亚男人的天堂| 看女生喷水的网站在线观看| 91午夜理伦私人影院| 一区二区三区网站| 秘密基地免费观看完整版中文 | 久久亚洲精品毛片| 精品午夜视频| 操bbb操bbb| 成人免费高清在线| 亚洲欧美综合自拍| 一区二区在线免费视频| 国产麻豆精品| 日本中文字幕亚洲| 国产欧美一区二区在线| 亚洲免费视频二区| 欧美成人午夜剧场免费观看| 高清一区二区三区| 中文字幕第21页| 亚洲欧美在线视频| 少妇高潮一区二区三区69| 欧美在线视频网| 91九色精品| 成人在线视频免费播放| 欧美亚洲一区二区在线观看| 菠萝蜜视频国产在线播放| 国产一区二区三区高清视频| 老司机久久99久久精品播放免费| 永久免费未视频| 亚洲国产欧美在线成人app| 国产一区二区三区朝在线观看| 青青视频免费在线| 久久免费美女视频| 国产三级伦理片| 日本精品va在线观看| 欧美疯狂party性派对| 一边摸一边做爽的视频17国产| 在线观看不卡视频| 超碰在线网站| 亚洲精品国产系列| caoporn国产精品| 国产露脸91国语对白| 欧美一级在线亚洲天堂| 亚洲精品a级片|