1. 程式人生 > >【玩轉SpringBoot】給自動配置來個整體大揭祕

【玩轉SpringBoot】給自動配置來個整體大揭祕

 

上一篇文章中提到的條件註解,只是自動配置整體解決方案中的一個環節而已,可以說是管中窺豹。

本文就逐步擦除迷霧,讓整體浮現出來,這樣就會有一個巨集觀的認識。


除了寫程式碼之外,還能幹點什麼?


提到“配置”這個詞,我們不一定知道它是什麼,但絕對知道它不是什麼,顯然,不是寫程式碼。

那對於使用者(使用SpringBoot框架的人)來說,除了寫程式碼,還能幹點什麼呢?這非常重要。

因為自動配置的整體方案最後必須落到“寫程式碼之外”的範圍來實現,這才叫配置,否則只能叫“編碼實現”了。

我認為以下這些內容,都不叫寫程式碼:

1)在application.yml配置檔案裡倒騰。


2)在原始碼的某些地方加上適合的註解。

3)在pom.xml裡使用maven引入適合依賴。

4)設定命令列引數,系統環境變數,JVM屬性等。

常用的基本上也就這些了。也就是說,自動配置的實現是逃不出這個圈兒的。

其實,配置檔案和註解上一篇已說過,已經用到自動配置當中了。

那下一個會是誰呢?


來吧,大家一起來思考設計方案


曾經有一句話,不想當將軍的士兵,不是好士兵。

現在有一句話,不想當架構師的碼農,不是好程式設計師。

我想說的是,如果你水平很高,做開發一樣很爽,如果水平很差,做了架構師一樣苦逼。

如果擁有了翱翔的翅膀,強大的心臟,聰明的頭腦,靈活的思維,開闊的視野,其實很多事情都會發生變化。

好了,那些想成為架構師的,請你來設計一個方案吧。

其實,方案根本就不是設計出來的,而是選擇出來的。

方案最終的好與壞並不那麼重要,只要能滿足要求,能讓大多數人接受,就可以了。

選擇依賴於判斷,判斷取決於分析,分析的目的就是要搞清事實現狀。

現狀就是,程式設計師喜歡寫程式碼,不喜歡寫文件和註釋。更不喜歡去設定命令列引數和環境變數等。

因為設定引數,通常意味著進行專案部署或元件調優,這大部分人都不喜歡,自然也不會在行。

假如要把方案落地到設定引數上來,我認為是一種不好的選擇。因為很難流行開來。

好吧,現在已經沒得選擇了,只剩下maven依賴了。因為程式設計師必須要會引入依賴,不然沒法寫程式碼。


SpringBoot提供的解決方案


首先要說明一個問題,有些人認為我們自己手動配置和SpringBoot提供的自動配置是不一樣的。

其實不是這樣的,在Spring裡面所有的配置其實都是bean的註冊和設定一些必要的引數。

比如我們手動配置redis,自然需要註冊幾個bean,再配置下IP、埠、密碼等。

SpringBoot的自動配置裡面也是包含這樣的程式碼的,都在原始碼裡呢,可以自己去看看。

這一點搞清楚後,接下來的就好理解了。

對於我們來說,想使用redis時,就手動註冊bean,不使用時就不註冊,這完全OK,沒有問題。

但對SpringBoot來說,這些註冊bean的程式碼必須寫好放到那裡,因為它也不知道使用者到底用不用redis。

這同時也說明了,這些註冊bean的程式碼預設是不會執行的,需要有一個類似“開關”的東西,在使用者使用時來開啟(或啟用)一下。

因此,包含兩個東西,一個是自動配置的程式碼,一個是啟用這些程式碼的“啟用器”。

這兩個東西在SpringBoot裡面是有名字的:

1)包含自動配置程式碼的叫做autoconfigure模組。

2)被稱為“啟用器”的叫做starter模組。

通常,這兩個模組會被打成兩個jar包。當然,也可以合成一個jar包,沒有影響。

如果足夠細心的話,會發現starter模組對應的jar包,通常是空的,即裡面沒有一個class(位元組碼)檔案。

如下圖01:

 

對於這個問題,需要解釋一下。我們剛剛之所以把starter模組稱為“啟用器”,只是為了方便理解而已。

其實它就是個普通的jar包,它存在的目的就是為了將autoconfigure模組對應的jar包引入,和所有其它依賴引入。

說白了,空jar包裡包含maven的pom檔案,可以用來引入依賴。如下圖0203:

 

這是一個日誌的starter對應的jar包的pom檔案。其實就是引入了日誌相關jar包。


對內建的和第三方接入的採用統一風格


SpringBoot肯定會內建一些自動配置(也可以認為是官方支援的),對於這些內建的,在實現時其實會容易一些,因為畢竟都在原始碼裡。

但是,也會有很多第三方的元件和SpringBoot整合,所以也需要自動配置,那怎樣做才能又簡單又好呢?來分析下吧。

自動配置其實就是註冊一些bean,這些註冊bean的程式碼肯定是放到一個類中(或者幾個類中),此時肯定會有一個類起到“入口”的作用。

但是這個入口類該怎麼去定位呢?都使用特定的類名嗎?好像實踐性不太好,因為每個人都應該有自己選擇類名的權利啊。

其實有個很好的示例可供我們參考,它就是main方法,main方法就是一個程式的執行入口,而且main方法所在的類名也是沒有限制的。

當我們打成一個jar包時,直接使用java -jar命令來執行,請問它是如何找到main方法了呢?逐個遍歷顯然是不可能的。

只要開啟jar包看一下就明白了。如下圖0405:

 

在jar包的META-INF/MANIFEST.MF檔案裡,指定了main方法所在的類。

進到這個類裡看看,確實有main方法,如下圖06:

 

其實這個jar包就是SpringBoot打成的可執行jar包。

這種方式是Java規定的,在一個固定的檔案中指定好Main-Class。這其實是依賴轉移。

把對main方法所在類名的依賴,轉移為對MANIFEST.MF這個檔案的依賴。

SpringBoot在解決自動配置類“入口”的問題時,就是採用這種方式的。

把對類名稱的依賴轉移為對固定檔名稱的依賴,在檔案中再去指定類名。

如下圖07:

 

在SpringBoot的jar包裡,META-INF目錄下有個spring.factories檔案。

這個檔名稱必須叫這個,開啟它,如下圖08:

 

可以看到這是一個屬性(properties)檔案格式的,裡面有一個key的名稱是:

org.springframework.boot.autoconfigure.EnableAutoConfiguration

這其實就是一個啟用自動配置的註解。

這個key的值是很多的類,這些類的名稱(通常)都以AutoConfiguration結尾,表示自動配置的“入口”類。

SpringBoot當然會專門來載入這些入口類啦,如下圖0910:

 

這樣第三方的jar包,只需要放置spring.factories這個檔案,並也使用這個key名稱,把值變成自己的自動配置入口類即可。

當jar包出現在類路徑中時,SpringBoot會掃描所有jar包裡的spring.factories這個檔案,就可以被處理了。

相當於一種自動識別,這樣就統一了SpringBoot的內建自動配置和第三方提供的自動配置。


自動配置的順序問題


上一篇文章介紹的註解基本都是對某種事物的檢測,看它是否存在或滿足特定條件。

以此來決定是否要進行自動配置。其實除了這之外,還有一個順序的問題。

就是有些需要先配置,然後才能配置其它的。這也可以通過註解來實現。

@AutoConfigureAfter註解指定應該在某個自動配置完成後再進行自己的。

@AutoConfigureBefore註解就正好和上面這個相反。

自動配置的內容還是非常多的,如果全部在原始碼中指定,可能會比較的亂。

所以SpringBoot就把一些內容給轉移了出來,放到jar包裡的一個properties檔案中。

如下圖11:

 

這個檔案中的內容很多。

>>> 玩轉SpringBoot系列文章 <<<

 

【玩轉SpringBoot】配置檔案yml的正確開啟姿勢

【玩轉SpringBoot】用好條件相關注解,開啟自動配置之門

 

>>> 品Spring系列文章 <<<

 

品Spring:帝國的基石

品Spring:bean定義上梁山

品Spring:實現bean定義時採用的“先進生產力”

品Spring:註解終於“成功上位”

品Spring:能工巧匠們對註解的“加持”

品Spring:SpringBoot和Spring到底有沒有本質的不同?

品Spring:負責bean定義註冊的兩個“排頭兵”

品Spring:SpringBoot輕鬆取勝bean定義註冊的“第一階段”

品Spring:SpringBoot發起bean定義註冊的“二次攻堅戰”

品Spring:註解之王@Configuration和它的一眾“小弟們”

品Spring:bean工廠後處理器的呼叫規則

品Spring:詳細解說bean後處理器

品Spring:對@PostConstruct和@PreDestroy註解的處理方法

相關推薦

SpringBoot自動配置整體揭祕

  上一篇文章中提到的條件註解,只是自動配置整體解決方案中的一個環節而已,可以說是管中窺豹。本文就逐步擦除迷霧,讓整體浮現出來,這樣就會有一個巨集觀的認識。除了寫程式碼之外,還能幹點什麼?提到“配置”這個詞,我們不一定知道它是什麼,但絕對知道它不是什麼,顯然,不是寫程式碼。

SpringBoot用好條件相關注解,開啟自動配置之門

自動配置隱含兩層含義,要搞清楚上帝讓程式設計師的髮量減少,是為了讓他變得更聰明,如果有一天聰明到了極點,那就是絕頂聰明。據說在大腦高速運轉下,這樣更有利於散熱,不至於核心溫度過高而產生告警。聰明的大腦是用來思考的,現在就來深入思考和分析下自動配置。自動配置包含兩層意思,一個是配置,一個是自動。這不廢話嘛。配置

SpringBoot配置檔案yml的正確開啟姿勢

序言在很久以前,Spring的配置檔案是基於XML的。它的名字就是applicationContext.xml,沒錯,就只有這一個xml檔案。它裡面配置了所有的東西。但是資料庫資訊通常會單獨拿出來,放入一個properties檔案,通常叫db.properties。後來覺著一個xml裡的東西實在太多了,就按功

SpringBoot非同步任務執行與其執行緒池配置

同步程式碼寫起來簡單,但就是怕遇到耗時操作,會影響效率和吞吐量。此時非同步程式碼才是王者,但涉及多執行緒和執行緒池,以及非同步結果的獲取,寫起來頗為麻煩。不過在遇到SpringBoot非同步任務時,這個問題就不存在了。因為Spring家族是最替使用者考慮的。結果就是,像同步一樣簡單,像非同步一樣強大。眾所熟悉

SpringBoot看似複雜的Environment其實很簡單

喜歡寫程式碼,討厭配環境我相信這十個字的小標題代表了大多數碼農的心聲。十年前讀大學時,學校開設了C語言還有C++。但是學習這兩種語言,對於新手來說非常沒有成就感。於是我就在校門口買個光碟,裝個VS(宇宙第一IDE),還有離線中文版MSDN(最牛的幫助文件),萬事已俱備。學習C#語法,看類的API,然後從Win

SpringBoot翻身做主人,一統web伺服器

寄人籬下的日子一直以來受傳統影響,我們的web工程總是打成war包,然後放入tomcat的webapps目錄下面。如下圖01: 當tomcat啟動時,會去解壓war包,然後執行web工程。這大家都非常熟悉了。用一個抽象的圖形表示,就是這樣子。如下圖02: 在一個大大的tomcat裡面,有一個小

SpringBoot讓錯誤處理重新由web伺服器接管

其實web伺服器是會處理錯誤的在web.xml還是隨處可見的年代時(確實有點老黃曆了),下面的這些配置應該都不陌生。根據錯誤程式碼處理錯誤,如下圖01: 根據異常型別處理錯誤,如下圖02: 不過我們更加熟悉的應該是SpringMVC的統一異常處理。如下圖03: 看到@Controlle

SpringBootSpringBoot應用的啟動過程一覽表

SpringBoot應用的啟動方式很簡單,就一行程式碼,如下圖01: 其實這行程式碼背後主要執行兩個方法,一個是構造方法,一個是run方法。構造方法主要內容就是收集一些資料,和確認一些資訊。如下圖02: 真正的執行要從run方法開始,為此,SpringBoot特意定義了一個監聽器,專門監聽這個

SpringBoot通過事件機制參與SpringBoot應用的啟動過程

生命週期和事件監聽一個應用的啟動過程和關閉過程是歸屬到“生命週期”這個概念的範疇。典型的設計是在啟動和關閉過程中會觸發一系列的“事件”,我們只要監聽這些事件,就能參與到這個過程中來。要想監聽事件,首先得有事件監聽器,就是常說的Listener。下面就是Sprin

開源BananaPi R2 —— 第二篇 Openwrt 網口配置分析

sign ati arr asi 1.0 tran spa 們的 errors 上次和大家分享了如何燒錄和安裝Openwrt到BananaPi R2,運行Openwrt的R2目前就具備路由器的功能了,這次我們來看看R2運行Openwrt的性能如何,同時也會講解一些常

Pod PresetK8S容器時區自動配置

摘要: 通過Pod Preset自動配置容器的時區 緣由 預設的情況,在K8S裡啟動一個容器,該容器的設定的時區是UTC0,但是對於很多客戶而言,其主機環境並不在UTC0。例如中國客戶在UTC8。如果不把容器的時區和主機主機設定為一致,則在查詢日誌等時候將非常不方便,也容

開源Linux C 檢測網口熱插拔

int NetDetect(char *net_name, int *statue) { int ret = 0; int skfd = 0; struct ifreq ifr; skfd = socket(AF_INET, SOCK_DGRAM, 0); //建議s

ExcelOracle PLSQL處理生成XLSX檔案

INTRODUCTION介紹    之前發表了一個研究心得(當然是站在別人的肩膀上的),在Oracle中直接用PL/SQL解析並讀取Excel的內容。很多人都感興趣,按照我的寫法也可以成功實現了。不過,有很多朋友提出了另外一個要求:讀取Excel是可以了,那是否可以在Ora

開源制作Docker鏡像

沒有 名稱 登錄 我們 nan utils str oar image 做嵌入式方向經常會遇到的一個問題,就是編譯環境安裝,如果換電腦,再重新安裝環境是一個比較費時的事情,這個時候可以自己制作一個Docker鏡像,然後把編譯環境在Docker鏡像裏面配置好,以後同步環境就非

Ubuntu11. Ubuntu上的瀏覽檔案命令nautilus

瀏覽檔案命令nautilus 先看一下它的幫助命令 [email protected]:~$ nautilus -h 用法: nautilus [選項...] [URI...] Browse the file system with the fil

GridView之簡單實現隱藏列

    做專案中有時候,如果設定了gridview隱藏列,問題就變得很簡單,所以小編總結了兩種實驗過的方法分享給大家。 第一種.     在gridview的RowCreated的方法中設定需要隱藏的

GridView之TemplateField模板

背景介紹:     近期負責開發的子系統中,很大一部分的工作都是和GridView打交道,各種編輯、刪除gridview的操作,所以小編準備系列總結,來進一步學習。     在介紹詳情之前,讓小編帶大家瞭解幾個重要角色。    介紹:在gridview 中單個欄位都會採用

GridView之隱藏域問題

   接著上篇部落格【GridView設定隱藏列方法】來說,這次小編將介紹一種更加方便的方法: 設定隱藏域:    在Gridview加一列使用模板,在模板裡定義隱藏域HiddenField控制元件,

Golangslice切片的操作——切片的追加、刪除、插入等

一、一般操作   1,宣告變數,go自動初始化為nil,長度:0,地址:0,nil func main(){ var ss []string; fmt.Printf("length:%v \taddr:%p \tisnil:%v",len(ss),ss, ss==nil) } -

開源BananaPi R2——移植RPi.GPIO 到 R2

機會 tin 循環輸出 nal 腳本 evel 3.1 我們 api 1. 首先給大家介紹一下什麽是RPi.GPIO. 簡單去講,RPi.GPIO就是一個運行在樹莓派開發板上可以通過Python去控制GPIO的一個中間件。 現在我這邊做了一個基礎功能的移