導航:首頁 > 源碼編譯 > autowired源碼深度解析

autowired源碼深度解析

發布時間:2025-03-10 02:39:02

Ⅰ 徹底搞明白Spring中的自動裝配和Autowired

當Spring裝配Bean屬性時,有時候非常明確,就是需要將某個Bean的引用裝配給指定屬性。比如,如果我們的應用上下文中只有一個 org.mybatis.spring.SqlSessionFactoryBean 類型的Bean,那麼任意一個依賴 SqlSessionFactoryBean 的其他Bean就是需要這個Bean。畢竟這里只有一個 SqlSessionFactoryBean 的Bean。

為了應對這種明確的裝配場景,Spring提供了自動裝配(autowiring)。與其顯式的裝配Bean屬性,為何不讓Spring識別出可以自動裝配的場景。

當涉及到自動裝配Bean的依賴關系時,Spring有多種處理方式。因此,Spring提供了4種自動裝配策略。

Spring在 AutowireCapableBeanFactory 介面中定義了這幾種策略。其中, AUTOWIRE_AUTODETECT 被標記為過時方法,在Spring3.0之後已經不再支持。

它的意思是,把與Bean的屬性具有相同名字的其他Bean自動裝配到Bean的對應屬性中。聽起來可能比較拗口,我們來看個例子。

首先,在User的Bean中有個屬性 Role myRole ,再創建一個Role的Bean,它的名字如果叫myRole,那麼在User中就可以使用byName來自動裝配。

上面是Bean的定義,再看配置文件。

如上所述,只要屬性名稱和Bean的名稱可以對應,那麼在user的Bean中就可以使用byName來自動裝配。那麼,如果屬性名稱對應不上呢?

是的,如果不使用屬性名稱來對應,你也可以選擇使用類型來自動裝配。它的意思是,把與Bean的屬性具有相同類型的其他Bean自動裝配到Bean的對應屬性中。

還是上面的例子,如果使用byType,Role Bean的ID都可以省去。

它是說,把與Bean的構造器入參具有相同類型的其他Bean自動裝配到Bean構造器的對應入參中。值的注意的是, 具有相同類型的其他Bean 這句話說明它在查找入參的時候,還是通過Bean的類型來確定。

構造器中入參的類型為Role

它首先會嘗試使用constructor進行自動裝配,如果失敗再嘗試使用byType。不過,它在Spring3.0之後已經被標記為 @Deprecated 。

默認情況下,default-autowire屬性被設置為none,標示所有的Bean都不使用自動裝配,除非Bean上配置了autowire屬性。
如果你需要為所有的Bean配置相同的autowire屬性,有個辦法可以簡化這一操作。
在根元素Beans上增加屬性 default-autowire="byType" 。

Spring自動裝配的優點不言而喻。但是事實上,在Spring XML配置文件里的自動裝配並不推薦使用,其中筆者認為最大的缺點在於不確定性。或者除非你對整個Spring應用中的所有Bean的情況了如指掌,不然隨著Bean的增多和關系復雜度的上升,情況可能會很糟糕。

從Spring2.5開始,開始支持使用註解來自動裝配Bean的屬性。它允許更細粒度的自動裝配,我們可以選擇性的標注某一個屬性來對其應用自動裝配。

Spring支持幾種不同的應用於自動裝配的註解。

我們今天只重點關注Autowired註解,關於它的解析和注入過程,請參考筆者Spring源碼系列的文章。 Spring源碼分析(二)bean的實例化和IOC依賴注入

使用@Autowired很簡單,在需要注入的屬性加入註解即可。

不過,使用它有幾個點需要注意。

默認情況下,它具有強制契約特性,其所標注的屬性必須是可裝配的。如果沒有Bean可以裝配到Autowired所標注的屬性或參數中,那麼你會看到 NoSuchBeanDefinitionException 的異常信息。

看到上面的源碼,我們可以得到這一信息,Bean集合為空不要緊,關鍵 isRequired 條件不能成立,那麼,如果我們不確定屬性是否可以裝配,可以這樣來使用Autowired。

我記得曾經有個面試題是這樣問的:Autowired是按照什麼策略來自動裝配的呢?

關於這個問題,不能一概而論,你不能簡單的說按照類型或者按照名稱。但可以確定的一點的是,它默認是按照類型來自動裝配的,即byType。

關鍵點 findAutowireCandidates 這個方法。

可以看到它返回的是一個列表,那麼就表明,按照類型匹配可能會查詢到多個實例。到底應該裝配哪個實例呢?我看有的文章里說,可以加註解以此規避。比如 @qulifier、@Primary 等,實際還有個簡單的辦法。

比如,按照UserService介面類型來裝配它的實現類。UserService介面有多個實現類,分為 UserServiceImpl、UserServiceImpl2 。那麼我們在注入的時候,就可以把屬性名稱定義為Bean實現類的名稱。

這樣的話,Spring會按照byName來進行裝配。首先,如果查到類型的多個實例,Spring已經做了判斷。

可以看出,如果查到多個實例, determineAutowireCandidate 方法就是關鍵。它來確定一個合適的Bean返回。其中一部分就是按照Bean的名稱來匹配。

最後我們回到問題上,得到的答案就是:@Autowired默認使用byType來裝配屬性,如果匹配到類型的多個實例,再通過byName來確定Bean。

上面我們已經看到了,通過byType可能會找到多個實例的Bean。然後再通過byName來確定一個合適的Bean,如果通過名稱也確定不了呢?
還是 determineAutowireCandidate 這個方法,它還有兩種方式來確定。

它的作用是看Bean上是否包含@Primary註解,如果包含就返回。當然了,你不能把多個Bean都設置為@Primary,不然你會得到 這個異常。

你也可以在Bean上配置@Priority註解,它有個int類型的屬性value,可以配置優先順序大小。數字越小的,就被優先匹配。同樣的,你也不能把多個Bean的優先順序配置成相同大小的數值,否則 異常照樣出來找你。

最後,有一點需要注意。Priority的包在 javax.annotation.Priority; ,如果想使用它還要引入一個坐標。

本章節重點闡述了Spring中的自動裝配的幾種策略,又通過源碼分析了Autowired註解的使用方式。
在Spring3.0之後,有效的自動裝配策略分為 byType、byName、constructor 三種方式。註解Autowired默認使用byType來自動裝配,如果存在類型的多個實例就嘗試使用byName匹配,如果通過byName也確定不了,可以通過Primary和Priority註解來確定。

閱讀全文

與autowired源碼深度解析相關的資料

熱點內容
優盤文件夾自動恢復 瀏覽:76
有伺服器怎麼製作小程序 瀏覽:132
程序員怎麼避開外包公司 瀏覽:604
刺激戰場國際服體驗伺服器滿了怎麼辦 瀏覽:487
python的number是什麼意思 瀏覽:539
剪映app怎麼把視頻鏡像 瀏覽:464
python長連接消息提醒 瀏覽:767
山西省美術演算法 瀏覽:95
華為手機怎麼不給別人刪app 瀏覽:814
c51單片機程序實例 瀏覽:112
騰訊幻核加密貓 瀏覽:782
雅思聽力真經pdf 瀏覽:442
甘肅戴爾伺服器虛擬化設計雲主機 瀏覽:236
怎麼購買蓋世童書APP 瀏覽:248
軍校的程序員 瀏覽:447
程序員被女警察追 瀏覽:455
剛畢業的程序員簡歷 瀏覽:696
安卓手機如何正確提升網速 瀏覽:248
linux系統編程教程 瀏覽:820
當程序員與bug 瀏覽:648