淘寶一面:“說一下 Spring Boot 自動裝配原理唄吞彤?”

每次問到 Spring Boot蔬咬, 面試官非常喜歡問這個問題:“講述一下 SpringBoot 自動裝配原理粤咪?”谚中。

我覺得我們可以從以下幾個方面回答:

什么是 SpringBoot 自動裝配?

SpringBoot 是如何實現(xiàn)自動裝配的寥枝?如何實現(xiàn)按需加載宪塔?

如何實現(xiàn)一個 Starter?

前言

使用過 Spring 的小伙伴囊拜,一定有被 XML 配置統(tǒng)治的恐懼某筐。即使 Spring 后面引入了基于注解的配置,我們在開啟某些 Spring 特性或者引入第三方依賴的時候冠跷,還是需要用 XML 或 Java 進行顯式配置南誊。

舉個例子。沒有 Spring Boot 的時候蜜托,我們寫一個 RestFul Web 服務(wù)抄囚,還首先需要進行如下配置。

spring-servlet.xml

但是橄务,Spring Boot 項目幔托,我們只需要添加相關(guān)依賴,無需配置蜂挪,通過啟動下面的main 方法即可重挑。

并且,我們通過 Spring Boot 的全局配置文件 application.properties或application.yml即可對項目進行設(shè)置比如更換端口號棠涮,配置 JPA 屬性等等攒驰。

為什么 Spring Boot 使用起來這么酸爽呢??這得益于其自動裝配故爵。自動裝配可以說是 Spring Boot 的核心,那究竟什么是自動裝配呢?

什么是 SpringBoot 自動裝配诬垂?

我們現(xiàn)在提到自動裝配的時候劲室,一般會和 Spring Boot 聯(lián)系在一起。但是结窘,實際上 Spring Framework 早就實現(xiàn)了這個功能很洋。Spring Boot 只是在其基礎(chǔ)上,通過 SPI 的方式隧枫,做了進一步優(yōu)化喉磁。

SpringBoot 定義了一套接口規(guī)范,這套規(guī)范規(guī)定:SpringBoot 在啟動時會掃描外部引用 jar 包中的META-INF/spring.factories文件官脓,將文件中配置的類型信息加載到 Spring 容器(此處涉及到 JVM 類加載機制與 Spring 的容器知識)协怒,并執(zhí)行類中定義的各種操作。對于外部 jar 來說卑笨,只需要按照 SpringBoot 定義的標準孕暇,就能將自己的功能裝置進 SpringBoot。

沒有 Spring Boot 的情況下赤兴,如果我們需要引入第三方依賴妖滔,需要手動配置,非常麻煩桶良。但是座舍,Spring Boot 中,我們直接引入一個 starter 即可陨帆。比如你想要在項目中使用 redis 的話曲秉,直接在項目中引入對應(yīng)的 starter 即可。

引入 starter 之后歧譬,我們通過少量注解和一些簡單的配置就能使用第三方組件提供的功能了岸浑。

在我看來,自動裝配可以簡單理解為:通過注解或者一些簡單的配置就能在 Spring Boot 的幫助下實現(xiàn)某塊功能瑰步。

SpringBoot 是如何實現(xiàn)自動裝配的矢洲?

我們先看一下 SpringBoot 的核心注解 SpringBootApplication 。

大概可以把 @SpringBootApplication看作是 @Configuration缩焦、@EnableAutoConfiguration读虏、@ComponentScan 注解的集合。根據(jù) SpringBoot 官網(wǎng)袁滥,這三個注解的作用分別是:

@EnableAutoConfiguration:啟用 SpringBoot 的自動配置機制

@Configuration:允許在上下文中注冊額外的 bean 或?qū)肫渌渲妙?/p>

@ComponentScan:掃描被@Component (@Service,@Controller)注解的 bean盖桥,注解默認會掃描啟動類所在的包下所有的類 ,可以自定義不掃描某些 bean题翻。如下圖所示揩徊,容器中將排除TypeExcludeFilter和AutoConfigurationExcludeFilter。

@EnableAutoConfiguration 是實現(xiàn)自動裝配的重要注解,我們以這個注解入手塑荒。

@EnableAutoConfiguration:實現(xiàn)自動裝配的核心注解

EnableAutoConfiguration 只是一個簡單地注解熄赡,自動裝配核心功能的實現(xiàn)實際是通過 AutoConfigurationImportSelector類。

我們現(xiàn)在重點分析下AutoConfigurationImportSelector 類到底做了什么齿税?

AutoConfigurationImportSelector:加載自動裝配類

AutoConfigurationImportSelector類的繼承體系如下:

可以看出彼硫,AutoConfigurationImportSelector 類實現(xiàn)了 ImportSelector接口,也就實現(xiàn)了這個接口中的 selectImports方法凌箕,該方法主要用于獲取所有符合條件的類的全限定類名拧篮,這些類需要被加載到 IoC 容器中

這里我們需要重點關(guān)注一下getAutoConfigurationEntry()方法牵舱,這個方法主要負責(zé)加載自動配置類的串绩。

該方法調(diào)用鏈如下:

現(xiàn)在我們結(jié)合getAutoConfigurationEntry()的源碼來詳細分析一下:

第 1 步:

判斷自動裝配開關(guān)是否打開。默認spring.boot.enableautoconfiguration=true仆葡,可在 application.properties 或 application.yml 中設(shè)置

第 2 步?:

用于獲取EnableAutoConfiguration注解中的 exclude 和 excludeName赏参。

第 3 步

獲取需要自動裝配的所有配置類,讀取META-INF/spring.factories

從下圖可以看到這個文件的配置內(nèi)容都被我們讀取到了沿盅。XXXAutoConfiguration的作用就是按需加載組件把篓。

不光是這個依賴下的META-INF/spring.factories被讀取到,所有 Spring Boot Starter 下的META-INF/spring.factories都會被讀取到腰涧。

所以韧掩,你可以清楚滴看到, druid 數(shù)據(jù)庫連接池的 Spring Boot Starter 就創(chuàng)建了META-INF/spring.factories文件窖铡。

如果疗锐,我們自己要創(chuàng)建一個 Spring Boot Starter,這一步是必不可少的费彼。

第 4 步?:

到這里可能面試官會問你:“spring.factories中這么多配置滑臊,每次啟動都要全部加載么?”箍铲。

很明顯雇卷,這是不現(xiàn)實的。我們 debug 到后面你會發(fā)現(xiàn)颠猴,configurations 的值變小了关划。

因為,這一步有經(jīng)歷了一遍篩選翘瓮,@ConditionalOnXXX 中的所有條件都滿足贮折,該類才會生效。

有興趣的童鞋可以詳細了解下 Spring Boot 提供的條件注解

@ConditionalOnBean:當容器里有指定 Bean 的條件下

@ConditionalOnMissingBean:當容器里沒有指定 Bean 的情況下

@ConditionalOnSingleCandidate:當指定 Bean 在容器中只有一個资盅,或者雖然有多個但是指定首選 Bean

@ConditionalOnClass:當類路徑下有指定類的條件下

@ConditionalOnMissingClass:當類路徑下沒有指定類的條件下

@ConditionalOnProperty:指定的屬性是否有指定的值

@ConditionalOnResource:類路徑是否有指定的值

@ConditionalOnExpression:基于 SpEL 表達式作為判斷條件

@ConditionalOnJava:基于 Java 版本作為判斷條件

@ConditionalOnJndi:在 JNDI 存在的條件下差在指定的位置

@ConditionalOnNotWebApplication:當前項目不是 Web 項目的條件下

@ConditionalOnWebApplication:當前項目是 Web 項 目的條件下

如何實現(xiàn)一個 Starter

光說不練假把式调榄,現(xiàn)在就來擼一個 starter踊赠,實現(xiàn)自定義線程池

第一步,創(chuàng)建threadpool-spring-boot-starter工程

第二步每庆,引入 Spring Boot 相關(guān)依賴

第三步臼疫,創(chuàng)建ThreadPoolAutoConfiguration

第四步,在threadpool-spring-boot-starter工程的 resources 包下創(chuàng)建META-INF/spring.factories文件

最后新建工程引入threadpool-spring-boot-starter

測試通過?勖稀!荣赶!


總結(jié)

Spring Boot 通過@EnableAutoConfiguration開啟自動裝配凤价,通過 SpringFactoriesLoader 最終加載META-INF/spring.factories中的自動配置類實現(xiàn)自動裝配,自動配置類其實就是通過@Conditional按需加載的配置類拔创,想要其生效必須引入spring-boot-starter-xxx包實現(xiàn)起步依賴

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末利诺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子剩燥,更是在濱河造成了極大的恐慌慢逾,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灭红,死亡現(xiàn)場離奇詭異侣滩,居然都是意外死亡,警方通過查閱死者的電腦和手機变擒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門君珠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人娇斑,你說我怎么就攤上這事策添。” “怎么了毫缆?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵唯竹,是天一觀的道長。 經(jīng)常有香客問我苦丁,道長浸颓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任芬骄,我火速辦了婚禮猾愿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘账阻。我一直安慰自己蒂秘,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布淘太。 她就那樣靜靜地躺著姻僧,像睡著了一般规丽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撇贺,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天赌莺,我揣著相機與錄音,去河邊找鬼松嘶。 笑死艘狭,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的翠订。 我是一名探鬼主播巢音,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尽超!你這毒婦竟也來了官撼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤似谁,失蹤者是張志新(化名)和其女友劉穎傲绣,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巩踏,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡秃诵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛀缝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顷链。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖屈梁,靈堂內(nèi)的尸體忽然破棺而出嗤练,到底是詐尸還是另有隱情,我是刑警寧澤在讶,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布煞抬,位于F島的核電站,受9級特大地震影響构哺,放射性物質(zhì)發(fā)生泄漏革答。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一曙强、第九天 我趴在偏房一處隱蔽的房頂上張望残拐。 院中可真熱鬧,春花似錦碟嘴、人聲如沸溪食。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽错沃。三九已至栅组,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間枢析,已是汗流浹背玉掸。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留醒叁,地道東北人司浪。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像把沼,于是被迫代替她去往敵國和親断傲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容