spring boot 源碼解析(二)配置文件

上一篇筆記詳細的說明的spring boot的一鍵啓動及其原理。也說到了自動配置。
但是有些時候我們並不想要這個默認配置,所以這個默認配置是可以修改的。而spring boot使用一個全局的配置文件,配置文件名是固定的:

  • application.properties
  • application.yml

配置文件的作用:修改SpringBoot自動配置的默認值
SpringBoot在底層將所有的東西都給我配置好了,但是總有些我們不滿意,所以就在配置文件裏配置。properties我們經常見,所以不多說了。主要說說yml。

YML

全稱:YAML (is not) a Markup Language (不)是一個標記語言
標記語言:xml是明顯的標記語言。而yml可以理解爲xml的簡化版。yml是以數據爲中心的。如下:
xml:

<server>
    <port>1234</port>
</server>

yml:

server:
  port: 1234
YML語法:
  1. 基本語法
    k: v 表示一對鍵值對(注意,冒號後面有個空格)
    以空格的縮進來控制層級關係。只要左對齊的一列數據,都是同一個層級的。
    屬性和值也是大小寫敏感的。
  2. 值的寫法
    字面量(數字,字符串,布爾):k: v直接寫就行。字符串默認不用加單引號或者雙引號。不過雙引號“”會轉義字符串裏面的特殊字符。也就是比如/n在雙引號中輸出會換行。單引號‘’不會轉義特殊字符。也就是引起來的是什麼就是什麼。
    對象和Map(屬性和值): k: v 在下一行來寫對象的屬性和值的關係。正常可以一個屬性佔一行。當然了也可以行內寫法
    yml中對象(map)寫法:
friends:
  name: zhang
  age: 20

yml中對象(map)行內寫法:

friends: {name: zhang,age: 20} 

數組(List,Set):用-值表示數組中的元素。行內的話中括號包裹
數組的寫法:

arr:
 - cat
 - dog
 - pig

數組的行內寫法:

arr: [cat,dog,pig]
YML的使用

剛剛說了這麼多YML的寫法,但是歸根結底我們還是要在實際中使用它。在實際中怎麼做到把yml文件注入呢?
其實也是一個很簡單的行爲,首先需要與實體屬性名稱對應。其次這個實體需要兩個註解修飾:

  • @Component(這個其實不僅是這個可以,只要把這個對象納入spring管理就行)
  • @ConfigurationProperties(prefix = "xxx")(需要注意這個前綴就是要綁定的最底層的名稱。)

下面用一個簡單的demo來展示下這個是怎麼使用的:

  1. 創建一個類:


  2. 將其屬性想要綁定的寫在yml文件上



    需要注意的是這個不用全部屬性。比如其中某個屬性沒有值不寫就行了。

  3. 其實到這就已經綁定上了,但是爲了確認結果所以我們實際使用下:


  4. 返回的就是我們預測到的內容。說明我們綁定成功了。


ps:注意下之前我們說過yml文件中大小寫敏感。而且其駝峯法和-是可以互換的。比如 user-name 是等價於userName的。
到此簡單的使用就完成了,其實properties也和這個用法差不多的。簡單說一下properties的用法:
前面的類不用動,properties的寫法:


然後我們訪問的結果如我們所想:

@Value和@ConfigurationProperties區別

其實簡單的看下二者的區別就能知道在二者中如何選取:

  • 如果說,我們只是在某個業務邏輯中需要獲取一下配置文件中的某個值,就使用@Value。
  • 如果說,我們專門編寫了一個javaBean來和配置文件進行映射,那麼我們直接使用@ConfigurationProperties

說到配置文件綁定,不得不提另外一個註解:
@PropertySource(value = {classpath:xxx.properties})
這個註解的用處是指定配置文件名稱去找配置文件(不指定會默認去application全局配置文件找)
還有一個:
@ImportResource:導入Spring的配置文件,讓配置文件裏面的內容生效
Spring Boot裏面沒有Spring的配置文件,我們自己編寫的配置文件也不能自動識別。想讓Spring的配置文件生效,加載進來要在啓動類上加上註解:
@ImportResource(locations={"claseepath:beans.xml"})
當然了這個用法本身就有問題,spring到spring boot進化到不用寫繁雜的xml了,在這我們再寫xml引入回去?這不就跟老祖宗用了幾百上千年好不容易簡化文字了,然後現在各種用繁體的腦回路一樣了麼?所以說對於spring boot中想使用spring 配置文件,我們換一種用法:
直接在spring boot的配置類中注入bean。如下使用方法:

配置文件中的表達式

  1. 可以使用隨機數:${random.XXXX}
  2. 可以用${xxx}獲取之前值的表達式。

Profile

關於這個Profile文件,其實是特別方便的一個實用性很強的工具。大概意思是我們在主配置文件編寫的時候,文件名可以是 application-{profile}.properties/yml。
默認使用的是application.properties的配置。但是我們可以選擇激活指定的profile文件。
如下demo中,三個配置文件,默認使用的是application.properties



仍然是這個三個配置文件,但是在全局配置文件中激活不同的版本號後,會啓動不同的配置文件:



當然了,好幾個文件來回切換也許有人會覺得麻煩(反正我不覺得,反而比yml的多文檔塊好用),所以yml有一種實現叫做多文檔塊。就是用三個-分割。每一個塊取一個文件名稱。然後最上面指定使用哪個塊的配置。也簡單的很,下面是使用demo:

其實這個yml和properties是差不多的。目前看起來似乎是yml更加方便,畢竟只有一個文件簡單明瞭。
但是大家想一個現實問題:正常我們一個項目,redis,mysql,甚至有的還用別的中間件。然後還有很多配置:默認下載路徑啊,圖片上傳路徑啊,最大線程數等等,這樣一個配置好幾十行。用多文檔塊的形式我個人是覺得很容易混淆。不過這個是我個人看法,具體還是要看大家習慣用哪個。

除了配置文件中指定版本,其實也可以在運行jar的時候命令行指定版本。如下:



如圖,明明配置文件中激活的是dev版本的配置,但是我在啓動jar的時候指定要用prod版本配置。結果是命令行的命令贏了,最終用prod配置啓動的。

配置文件優先級

按照正常的習慣,我們一般配置文件都在resources下面,但是其實配置文件不僅僅可以在這個下面。
事實上配置文件可以在四個位置:

  1. 項目根目錄的config文件下
  2. 項目根目錄下
  3. 項目resources的config文件下
  4. 項目resources下
    上面四個的優先級是從高到低的,下面我們一個個測試一下:



    如圖兩個位置的配置文件,最終實現了的是config文件下的。



注意下,這個高優先級的配置會覆蓋低優先級的配置。這個要注意,A,B,C,D四個配置文件,不是說只讀優先級最高的那個。而是每個都會讀取。只不過如果有相同的配置,會以最高優先級的爲主。其實這四個文件可以形成互補配置!

另外注意當項目打好包以後,在運行jar的時候,是可以用命令行參數的形式指定配置文件的位置(--spring.config.location=文件全路徑名)。而指定配置文件和默認加載的這些配置文件會共同起作用形成互補配置。
需要注意的是:命令行指定的配置文件,是最高級的!

外部配置加載順序

SpringBoot也可以從下面的位置加載配置(從高到低,高優先級的會覆蓋低優先級的配置,所有的配置都會形成互補配置)

  1. 命令行參數
  2. 來自java:comp/env的NDI屬性
  3. java系統屬性
  4. 操作系統環境變量
  5. jar包外部的application-{profile}.properties/yml
  6. jar包內部的application-{profile}.properties/yml
    ...
    實際上官方文檔中有17中配置方法。但是太多了就不一一說明了,用到的時候可以自己去查看官方文檔。

Spring Boot自動配置原理

配置文件到底能寫什麼?怎麼寫?
這個官方文檔列出來能配置的屬性,但是這個其實特別長。主要弄懂自動配置原理,就能知道怎麼用了。

自動配置原理(這個其實上一章就介紹了,在講啓動類的時候):
  1. SpringBoot啓動的時候加載主配置類,開啓了自動配置功能@EnableAutoConfiguration
  2. @EnableAutoConfiguration作用:有個SpringFactoriesLoader類,這個類會獲取項目類路徑下META-INF/spring.factories中的所有properties文件對應的配置類類名添加到容器中。
    總結起來一句話:將類路徑下MATE-INF/spring.factories裏面的所有配置類納入容器中。
  3. 每一個自動配置類進行自動配置功能。
  4. 每個配置類上都有個註解,其中綁定的就是我們配置文件中的屬性名稱。*
  5. 所有在配置文件中能夠配置的屬性都是在XXXproperties類種中封裝的。配置文件能配置什麼可以參照某個功能對應的這個屬性類。
  6. 根據不用的條件判斷,會決定這個類是否會生效,一旦這個配置類生效了,在只有一個有參構造器的情況下,參數的只會從容器中拿,並且會給容器中添加一個組件。這個組件中的值就是從properties中獲取的。

所以總結一下:我們能配置的屬性,都是來源於這個功能的properties類
精髓

  • SpringBoot啓動會加載大量的自動配置類
  • 我們看我們需要的功能有沒有SpringBoot默認寫好的自動配置類。
  • 我們在看這個自動配置類中到底配置了哪些組件,如果我們要的組件springBoot中有,我們就不需要額外配置了
  • 給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性,我們可以在配置文件中指定這些屬性的值。

SpringBoot中:
XXXAutoConfiguration:自動配置類,給容器中添加組件
XXXProperties:封裝配置文件中相關屬性

@Conditional及其派生註解:
@Conditional是判斷是否滿足某條件,滿足則生效。


自動配置類一定在滿足一定的條件才生效。
這個也就是我們啓動springBoot,雖然加載了很多自動配置,但是很多是不滿足註解條件,所以不生效的。
怎麼知道哪些配置生效了,哪些沒生效呢?
可以在配置中配置debug=true。
這樣啓動項目的時候會有自動配置報告:輸出所有啓動了的配置。也會輸出沒有啓動的配置。

至此,這個springboot中的關於配置的講解到此結束,如果稍微幫到你了記得點個喜歡點個關注。也祝大家工作順順利利!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章