面試官:說說Spring Boot自動裝配的原理唄!

來源:blog.csdn.net/u014745069/

article/details/83820511

引言

不論在工作中,亦或是求職面試,Spring Boot已經成爲我們必知必會的技能項。除了某些老舊的政府項目或金融項目持有觀望態度外,如今的各行各業都在飛速的擁抱這個已經不是很新的Spring啓動框架。

當然,作爲Spring Boot的精髓,自動配置原理的工作過程往往只有在“面試”的時候才能用得上,但是如果在工作中你能夠深入的理解Spring Boot的自動配置原理,將無往不利。

Spring Boot的出現,得益於“習慣優於配置”的理念,沒有繁瑣的配置、難以集成的內容(大多數流行第三方技術都被集成),這是基於Spring 4.x提供的按條件配置Bean的能力。

Spring Boot的配置文件

初識Spring Boot時我們就知道,Spring Boot有一個全局配置文件:application.propertiesapplication.yml

我們的各種屬性都可以在這個文件中進行配置,最常配置的比如:server.portlogging.level.* 等等,然而我們實際用到的往往只是很少的一部分,那麼這些屬性是否有據可依呢?答案當然是肯定的,這些屬性都可以在官方文檔中查找到:

https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#common-application-properties

(所以,話又說回來,找資料還得是官方文檔,百度出來一大堆,還是稍顯業餘了一些)

除了官方文檔爲我們提供了大量的屬性解釋,我們也可以使用IDE的相關提示功能,比如IDEA的自動提示,和Eclipse的YEdit插件,都可以很好的對你需要配置的屬性進行提示,下圖是使用Eclipse的YEdit插件的效果,Eclipse的版本是:STS 4。

以上,是Spring Boot的配置文件的大致使用方法,其實都是些題外話。

那麼問題來了:這些配置是如何在Spring Boot項目中生效的呢? 那麼接下來,就需要聚焦本篇博客的主題:自動配置工作原理或者叫實現方式。

工作原理剖析

Spring Boot關於自動配置的源碼在spring-boot-autoconfigure-x.x.x.x.jar中:

當然,自動配置原理的相關描述,官方文檔貌似是沒有提及。不過我們不難猜出,Spring Boot的啓動類上有一個@SpringBootApplication註解,這個註解是Spring Boot項目必不可少的註解。那麼自動配置原理一定和這個註解有着千絲萬縷的聯繫!

@EnableAutoConfiguration

@SpringBootApplication是一個複合註解或派生註解,在@SpringBootApplication中有一個註解@EnableAutoConfiguration,翻譯成人話就是開啓自動配置,其定義如下:

而這個註解也是一個派生註解,其中的關鍵功能由@Import提供,其導入的AutoConfigurationImportSelector的selectImports()方法通過SpringFactoriesLoader.loadFactoryNames()掃描所有具有META-INF/spring.factories 的jar包。spring-boot-autoconfigure-x.x.x.x.jar裏就有一個這樣的spring.factories文件。

這個spring.factories文件也是一組一組的key=value的形式,其中一個key是EnableAutoConfiguration類的全類名,而它的value是一個xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔,如下圖所示:

這個@EnableAutoConfiguration註解通過@SpringBootApplication被間接的標記在了Spring Boot的啓動類上。在SpringApplication.run(...)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類加載到Spring容器中。


自動配置生效

每一個XxxxAutoConfiguration自動配置類都是在某些條件之下才會生效的,這些條件的限制在Spring Boot中以註解的形式體現,常見的條件註解有如下幾項:

  • @ConditionalOnBean:當容器裏有指定的bean的條件下。
  • @ConditionalOnMissingBean:當容器裏不存在指定bean的條件下。
  • @ConditionalOnClass:當類路徑下有指定類的條件下。
  • @ConditionalOnMissingClass:當類路徑下不存在指定類的條件下。
  • @ConditionalOnProperty:指定的屬性是否有指定的值,比如 @ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表當xxx.xxx爲enable時條件的布爾值爲true,如果沒有設置的情況下也爲true。

ServletWebServerFactoryAutoConfiguration配置類爲例,解釋一下全局配置文件中的屬性如何生效,比如:server.port=8081,是如何生效的(當然不配置也會有默認值,這個默認值來自於org.apache.catalina.startup.Tomcat)。

ServletWebServerFactoryAutoConfiguration類上,有一個@EnableConfigurationProperties註解:開啓配置屬性,而它後面的參數是一個ServerProperties類,這就是習慣優於配置的最終落地點。

在這個類上,我們看到了一個非常熟悉的註解@ConfigurationProperties,它的作用就是從配置文件中綁定屬性到對應的bean上,而@EnableConfigurationProperties負責導入這個已經綁定了屬性的bean到spring容器中(見上面截圖)。那麼所有其他的和這個類相關的屬性都可以在全局配置文件中定義,也就是說,真正“限制”我們可以在全局配置文件中配置哪些屬性的類就是這些XxxxProperties類,它與配置文件中定義的prefix關鍵字開頭的一組屬性是唯一對應的。

至此,我們大致可以瞭解。在全局配置的屬性如:server.port等,通過@ConfigurationProperties註解,綁定到對應的XxxxProperties配置實體類上封裝爲一個bean,然後再通過@EnableConfigurationProperties註解導入到Spring容器中。

而諸多的XxxxAutoConfiguration自動配置類,就是Spring容器的JavaConfig形式,作用就是爲Spring 容器導入bean,而所有導入的bean所需要的屬性都通過xxxxProperties的bean來獲得。

可能到目前爲止還是有所疑惑,但面試的時候,其實遠遠不需要回答的這麼具體,你只需要這樣回答:

Spring Boot啓動的時候會通過@EnableAutoConfiguration註解找到META-INF/spring.factories配置文件中的所有自動配置類,並對其進行加載,而這些自動配置類都是以AutoConfiguration結尾來命名的,它實際上就是一個JavaConfig形式的Spring容器配置類,它能通過以Properties結尾命名的類中取得在全局配置文件中配置的屬性如:server.port,而XxxxProperties類是通過@ConfigurationProperties註解與全局配置文件中對應的屬性進行綁定的。

通過一張圖標來理解一下這一繁複的流程:

圖片來自於王福強老師的博客:https://afoo.me/posts/2015-07-09-how-spring-boot-works.html

總結

綜上是對自動配置原理的講解。當然,在瀏覽源碼的時候一定要記得不要太過拘泥與代碼的實現,而是應該抓住重點脈絡。

一定要記得XxxxProperties類的含義是:封裝配置文件中相關屬性;XxxxAutoConfiguration類的含義是:自動配置類,目的是給容器中添加組件。

而其他的主方法啓動,則是爲了加載這些五花八門的XxxxAutoConfiguration類。


   
   
   
   
      
      
      
     
        
        
        
明天見(。・ω・。)ノ♡

本文分享自微信公衆號 - Java識堂(erlieStar)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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