【玩轉SpringBoot】用好條件相關注解,開啟自動配置之門
自動配置隱含兩層含義,要搞清楚
上帝讓程式設計師的髮量減少,是為了讓他變得更聰明,如果有一天聰明到了極點,那就是絕頂聰明。
據說在大腦高速運轉下,這樣更有利於散熱,不至於核心溫度過高而產生告警。
聰明的大腦是用來思考的,現在就來深入思考和分析下自動配置。
自動配置包含兩層意思,一個是配置,一個是自動。這不廢話嘛。
配置存在的一個前提是,要有選擇才行,如果沒得選擇,就不用談配置了。
比如十幾年前讀大學時,無論是回家還是去學校,都只能坐最便宜的硬座。因為沒得選擇。
現在情況就不一樣了,高鐵、動車、飛機都可以了。有了選擇,就可以談配置了。
所以配置就是在一些可選項裡做出選擇,既然是選擇,就需要有選擇的依據/理由。
如果距離不太遠的話,選擇高鐵,這樣在花費的時間和金錢上是相對均衡的。
如果此時想稍微省點錢的話,選擇動車,不過花的時間稍多些。也算一種取捨吧。
如果距離太遠的話,選擇飛機,這樣時間和金錢上才是最均衡的。
這些列舉出來的影響選擇的因素,其實就是“條件”。因此,配置就是根據條件做出選擇。
那自動的意思就是,使用工具或一套程式根據條件做出選擇,最後只把結果告訴我們即可。
就是說,我們不參與選擇的過程,我們只需提供一些和“條件”相關的資訊即可。
Spring的風格,萬物皆可註解
通過上一小節,我們成功的把自動配置轉化為條件和工具。
回到程式裡,條件指的是什麼?如果不知道的話,那條件語句指的是什麼?
就是if...else,要根據條件做出判斷,所以條件就是某種形式的程式程式碼。
那工具呢?就是一些常用程式碼或演算法的集合嘛。也是某種形式的程式程式碼。
條件和工具已經被成功的轉化為了程式程式碼,現在來看,自動配置就等於程式程式碼。
關鍵是這個程式程式碼是讓我們來寫嗎?如果是的話,那可就產生悖論了。
因為配置通常意味著不寫程式碼,如果還要寫程式碼的話,那就不叫配置了,叫搞笑了。
因此,條件和工具的程式程式碼,SpringBoot都寫好了,並通過註解進行了封裝。
最後把這些註解暴露出來,供使用者使用,這就是條件註解的由來。
使用者可以通過設定註解屬性把“條件”相關資訊傳遞進去,讓底層的“工具”進行判斷和選擇。
最終,不同的條件產生了不同的行為,達到了自動配置的目的。
官方提供的常用條件註解
因為Spring的核心是基於bean的,所以這些條件註解主要是影響bean的註冊。
因為註冊的bean不同了,最後對外呈現的行為就不同了。不就是自動配置了。
一、最常用的應該是@Profile註解了
根據不同的環境可以註冊不同的bean,如下圖01:
首先,不啟用任何環境,執行一下,結果如下圖02:
可以看到,沒有啟用任何環境,所以預設是default。因此Default類就被註冊了。
然後,啟用一下prod環境,在IDE裡設定一下,如下圖03:
再次執行一下,結果如下圖04:
可以看到,prod環境被激活了,所以Prod類就被註冊了。
SpringBoot內建了一些註解,如下圖05:
我們關注一些常用的就可以了。
二、@ConditionalOnProperty註解
這個註解用於檢測Environment中的指定屬性是否存在或等於某個指定的值。
如下圖06:
如havingValue屬性沒有指定的話,那麼只要實際屬性值不等於false,都算匹配成功。如果指定了,那就必須要一樣才行。
matchIfMissing屬性就是說,如果沒有發現這個屬性,算不算匹配上,設定為true就算,false就不算,預設為不算。
請看配置檔案,如下圖07:
很明顯,這是可以匹配上的,執行一下,結果如下圖08:
可以看到,對應的類被註冊了bean定義。
三、@ConditionalOnClass註解
這個註解用於檢測類路徑裡是否包含某個類,其實就是確定是否引入了指定的依賴。
如下圖09:
因為我用的JDK1.8,肯定有這個類,所以會匹配上,結果如下圖10:
注:@ConditionalOnMissingClass註解原理一樣,只不過是否定性的匹配而已。
四、@ConditionalOnBean註解
這個註解用於檢測容器中是否包含指定的bean。如下圖11:
除了可以用Class<?>指定bean外,還可以使用類的全名稱,還可以使用bean名稱(即beanName)。
還可以使用註解指定是否包含標有該註解的bean。
示例中是通過Class<?>來指定的,而且指定的是之前註冊過的bean,所以一定能匹配上。
執行結果如下圖12:
注:@ConditionalOnMissingBean註解原理一樣,只不過是否定性的匹配而已。
五、@ConditionalOnSingleCandidate註解
這個註解用於檢測容器中能夠匹配上的候選bean是否只有一個。
只有一個是什麼意思呢?就是某個類只註冊了一次,這時就是隻有一個。比如Boss類。
但是員工可以有多個,所以就會有多個Staff類被註冊。此時就不滿足條件了。
如果此時還想滿足的話,就必須在其中一個Staff類註冊時標上@Primary註解。
如下圖13:
因為我們指定的bean只註冊了一次,所以一定滿足條件。
執行結果如下圖14:
六、@ConditionalOnResource註解
這個註解用於檢測類路徑中是否包含指定的資源。一般也就是檔案了。
我們來檢測下配置檔案,如下圖15:
肯定是存在的,執行結果如下圖16:
自定義條件註解
需要實現一個條件介面,如下圖17:
只有一個方法,返回true表示匹配上,false則相反。
方法的第一個引數,是一個上下文,如下圖18:
這裡有很多的東西供我們使用。
方法的第二個引數,是最終標有我們定義好的條件註解的那個類,這個一定要明白。
我們來定義兩個和作業系統對應的註解,一個用於Windows,一個用於Linux。
Windows版本的實現,如下圖19:
從Environment中讀出作業系統的名稱,看是否包含windows即可。
Linux版本的實現,如下圖20:
原理和剛剛的一樣。
再定義兩個註解,分別和這兩個條件實現類關聯起來。
Windows版本的,如下圖21
Linux版本的,如下圖22:
然後開始試用一下這兩個條件註解,如下圖23:
因為我用的是Windows,所以肯定只有@Windows註解可以匹配。
執行結果如下圖24:
這只是一個簡單的示例,可以根據自己的需要定義更加複雜的,但是原理和流程都是一樣的。
>>> 玩轉SpringBoot系列文章 <<<
【玩轉SpringBoot】配置檔案yml的正確開啟姿勢
>>> 品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後處理器
相關推薦
【玩轉SpringBoot】用好條件相關注解,開啟自動配置之門
自動配置隱含兩層含義,要搞清楚上帝讓程式設計師的髮量減少,是為了讓他變得更聰明,如果有一天聰明到了極點,那就是絕頂聰明。據說在大腦高速運轉下,這樣更有利於散熱,不至於核心溫度過高而產生告警。聰明的大腦是用來思考的,現在就來深入思考和分析下自動配置。自動配置包含兩層意思,一個是配置,一個是自動。這不廢話嘛。配置
【玩轉SpringBoot】配置檔案yml的正確開啟姿勢
序言在很久以前,Spring的配置檔案是基於XML的。它的名字就是applicationContext.xml,沒錯,就只有這一個xml檔案。它裡面配置了所有的東西。但是資料庫資訊通常會單獨拿出來,放入一個properties檔案,通常叫db.properties。後來覺著一個xml裡的東西實在太多了,就按功
【玩轉SpringBoot】給自動配置來個整體大揭祕
上一篇文章中提到的條件註解,只是自動配置整體解決方案中的一個環節而已,可以說是管中窺豹。本文就逐步擦除迷霧,讓整體浮現出來,這樣就會有一個巨集觀的認識。除了寫程式碼之外,還能幹點什麼?提到“配置”這個詞,我們不一定知道它是什麼,但絕對知道它不是什麼,顯然,不是寫程式碼。
【玩轉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
【玩轉SpringBoot】SpringBoot應用的啟動過程一覽表
SpringBoot應用的啟動方式很簡單,就一行程式碼,如下圖01: 其實這行程式碼背後主要執行兩個方法,一個是構造方法,一個是run方法。構造方法主要內容就是收集一些資料,和確認一些資訊。如下圖02: 真正的執行要從run方法開始,為此,SpringBoot特意定義了一個監聽器,專門監聽這個
【玩轉SpringBoot】通過事件機制參與SpringBoot應用的啟動過程
生命週期和事件監聽一個應用的啟動過程和關閉過程是歸屬到“生命週期”這個概念的範疇。典型的設計是在啟動和關閉過程中會觸發一系列的“事件”,我們只要監聽這些事件,就能參與到這個過程中來。要想監聽事件,首先得有事件監聽器,就是常說的Listener。下面就是Sprin
【玩轉SpringBoot】非同步任務執行與其執行緒池配置
同步程式碼寫起來簡單,但就是怕遇到耗時操作,會影響效率和吞吐量。此時非同步程式碼才是王者,但涉及多執行緒和執行緒池,以及非同步結果的獲取,寫起來頗為麻煩。不過在遇到SpringBoot非同步任務時,這個問題就不存在了。因為Spring家族是最替使用者考慮的。結果就是,像同步一樣簡單,像非同步一樣強大。眾所熟悉
【玩轉開源】BananaPi R2 —— 第二篇 Openwrt 網口配置分析
sign ati arr asi 1.0 tran spa 們的 errors 上次和大家分享了如何燒錄和安裝Openwrt到BananaPi R2,運行Openwrt的R2目前就具備路由器的功能了,這次我們來看看R2運行Openwrt的性能如何,同時也會講解一些常
【玩轉開源】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
【玩轉Excel】Oracle PLSQL處理生成XLSX檔案
INTRODUCTION介紹 之前發表了一個研究心得(當然是站在別人的肩膀上的),在Oracle中直接用PL/SQL解析並讀取Excel的內容。很多人都感興趣,按照我的寫法也可以成功實現了。不過,有很多朋友提出了另外一個要求:讀取Excel是可以了,那是否可以在Ora
【玩轉開源】制作Docker鏡像
沒有 名稱 登錄 我們 nan utils str oar image 做嵌入式方向經常會遇到的一個問題,就是編譯環境安裝,如果換電腦,再重新安裝環境是一個比較費時的事情,這個時候可以自己制作一個Docker鏡像,然後把編譯環境在Docker鏡像裏面配置好,以後同步環境就非
【玩轉Ubuntu】11. 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控制元件,
【玩轉Golang】slice切片的操作——切片的追加、刪除、插入等
一、一般操作 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的一個中間件。 現在我這邊做了一個基礎功能的移
【玩轉資料結構 從入門到進階】 佇列
package Arr; /** * 陣列佇列 * @author 大南海 * * @param <E> */ public class ArrayQueue<E> implements Queue<E> { private Array<E