【玩轉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注解的處理方法

品Spring:對@Resource注解的處理方法

品Spring:對@Autowired和@Value注解的處理方法

品Spring:真沒想到,三十步才能完成一個bean實例的創建

品Spring:關於@Scheduled定時任務的思考與探索,結果尷尬了

 

>>> 熱門文章集錦 <<<

 

畢業10年,我有話說

【面試】我是如何面試別人List相關知識的,深度有點長文

我是如何在畢業不久只用1年就升為開發組長的

爸爸又給Spring MVC生了個弟弟叫Spring WebFlux

【面試】我是如何在面試別人Spring事務時“套路”對方的

【面試】Spring事務面試考點吐血整理(建議珍藏)

【面試】我是如何在面試別人Redis相關知識時“軟懟”他的

【面試】吃透了這些Redis知識點,面試官一定覺得你很NB(干貨 | 建議珍藏)

【面試】如果你這樣回答“什么是線程安全”,面試官都會對你刮目相看(建議珍藏)

【面試】迄今為止把同步/異步/阻塞/非阻塞/BIO/NIO/AIO講的這么清楚的好文章(快快珍藏)

【面試】一篇文章幫你徹底搞清楚“I/O多路復用”和“異步I/O”的前世今生(深度好文,建議珍藏)

【面試】如果把線程當作一個人來對待,所有問題都瞬間明白了

Java多線程通關———基礎知識挑戰

品Spring:帝國的基石

 

作者是工作超過10年的碼農,現在任架構師。喜歡研究技術,崇尚簡單快樂。追求以通俗易懂的語言解說技術,希望所有的讀者都能看懂並記住。下面是公眾號的二維碼,歡迎關注!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM