Spring探索:既生Resource,何生Autowired?
提到Spring依賴注入,大家最先想到應該是@Resource和@Autowired,很多文章只是講解了功能上的區別,對於Spring為什麼要支援兩個這麼類似的註解卻未提到,屬於知其然而不知其所以然。不知大家在使用這兩個註解的時候有沒有想過,@Resource又支援名字又支援型別,還要@Autowired幹嘛,難道是Spring官方沒事做了?
真的是沒事做了嗎?讀了本文你將會了解到:
@Resource和@Autowired來源
Spring官方為什麼會支援這兩個功能如此相似的註解?
為什麼@Autowired屬性注入的時候Idea會曝出黃色的警告?
@Resource和@Autowired推薦用法
來源
既然要弄清楚,就要先了解他們的身世。
@Resource 於 2006年5月11日隨著JSR 250 釋出 ,官方解釋是:
Resource 註釋標記了應用程式需要的資源。該註解可以應用於應用程式元件類,或元件類的欄位或方法。當註解應用於欄位或方法時,容器將在元件初始化時將所請求資源的例項注入到應用程式元件中。如果註釋應用於元件類,則註釋宣告應用程式將在執行時查詢的資源。
可以看到它類似一個定義,而由其他的元件或框架自由實現。
@Autowired 於 2007年11月19日隨著Spring2.5釋出,同時官方也對@Resource進行了支援。@Autowired的官方解釋是:
將建構函式、欄位、設定方法或配置方法標記為由 Spring 的依賴注入工具自動裝配。
可以看到,@Autowired 是 Spring的親兒子,而@Resource是Spring對它定義的一種實現,它們的功能如此相似。那麼為什麼要支援了@Resource,又要自己搞個@Autowired呢?
對此專門查了一下Spring2.5的官方文件,文件中有一段這麼說到:
However, Spring 2.5 dramatically changes the landscape. As described above, the autowiring choices have now been extended with support for the JSR-250 @Resource annotation to enable autowiring of named resources on a per-method or per-field basis. However, the @Resource annotation alone does have some limitations. Spring 2.5 therefore introduces an @Autowired annotation to further increase the level of control.
大概的意思是說,Spring2.5 支援註解自動裝配啦, 現已經支援JSR-250 @Resource 基於每個方法或每個欄位的命名資源的自動裝配,但是隻有@Resource是不行的,我們還推出了“粒度”更大的@Autowired,來覆蓋更多場景了。
嗯哼,那麼官方說的“粒度”就是關鍵了,那“粒度”指的是什麼呢”?
既生“@Resource”,何生“@Autowired”
要想找到粒度是什麼,我們先從兩個註解的功能下手
@Autowired
型別注入
@Resource
名字注入優先,找不到名字找型別
論功能的“粒度”,@Resource已經包含@Autowired了啊,“粒度”更大啊,難道是Spring2.5的時候還不是這樣?我又去翻了下Spring2.5文件,上面明確的寫到:
When using @Resource without an explicitly provided name, if no Spring-managed object is found for the default name, the injection mechanism will fallback to a type-match.
這不是和現在一樣的嗎,我此時凌亂了。那麼“粒度”到底指的是什麼?在混跡眾多論壇後,其中stackoverflow的一段話引起了我的注意:
Both @Autowired and @Resource work equally well. But there is a conceptual difference or a difference in the meaning.
@Resource
means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.
@Inject
or
@Autowired
try to wire in a suitable other component by type.
So, basically these are two quite distinct concepts. Unfortunately the Spring-Implementation of @Resource has a built-in fallback, which kicks in when resolution by-name fails. In this case, it falls back to the @Autowired-kind resolution by-type. While this fallback is convenient, IMHO it causes a lot of confusion, because people are.
大概的意思是:Spring雖然實現了兩個功能類似的,但是存在概念上的差異或含義上的差異:
@Resource 這按名稱給我一個確定已知的資源。
@Autowired 嘗試按型別連線合適的其他元件。
但是@Resource當按名稱解析失敗時會啟動。在這種情況下,它會按型別解析,引起概念上的混亂,因為開發者沒有意識到概念上的差異,而是傾向於使用@Resource基於型別的自動裝配。
原來Spring官方說的“粒度”是指“資源範圍”,@Resource找尋的是確定的已知的資源,相當於給你一個座標,你直接去找。@Autowired是在一片區域裡面嘗試搜尋合適的資源。
所以上面的問題答案已經基本明確了。
Spring為什麼會支援兩個功能相似的註解呢?
它們的概念不同,@Resource更傾向於找已知資源,而Autowired傾向於嘗試按型別搜尋資源。
方便其他框架遷移,@Resource是一種規範,只要符合JSR-250規範的其他框架,Spring就可以相容。
既然@Resource更傾向於找已知資源,為什麼也有按型別注入的功能?
個人猜測:可能是為了相容從Spring切換到其他框架,開發者就算只使用Resource也是保持Spring強大的依賴注入功能。
Spring的區別對待
看到這相信大家對使用@Resource還是@Autowired有了自己的見解。在日常寫程式碼中有個小細節不知道大家有沒有注意到,使用@Autowired在屬性上的時候Idea會曝出黃色的警告,並且推薦我們使用構造方法注入,而Resource就不會,這是為什麼呢?警告如下:
為什麼@Autowired在屬性上的時候Idea會曝出黃色的警告,並且推薦我們使用構造方法注入?
其實Spring文件中已經給出了答案,主要有這幾點:
1、宣告不了常量的屬性
基於屬性的依賴注入不適用於宣告為 final 的欄位,因為此欄位必須在類例項化時去例項化。宣告不可變依賴項的唯一方法是使用基於建構函式的依賴項注入。
2、容易忽視類的單一原則
一個類應該只負責軟體應用程式功能的單個部分,並且它的所有服務都應該與該職責緊密結合。如果使用屬性的依賴注入,在你的類中很容易有很多依賴,一切看起來都很正常。但是如果改用基於建構函式的依賴注入,隨著更多的依賴被新增到你的類中,建構函式會變得越來越大,程式碼開始就開始出現“異味”,發出明確的訊號表明有問題。具有超過十個引數的建構函式清楚地表明該類有太多的依賴,讓你不得不注意該類的單一問題了。因此,屬性注入雖然不直接打破單一原則,但它卻可以幫你忽視單一原則。
3、迴圈依賴問題
A類透過建構函式注入需要B類的例項,B類透過建構函式注入需要A類的例項。如果你為類 A 和 B 配置 bean 以相互注入,使用構造方法就能很快發現。
4、依賴注入強依賴Spring容器
如果您想在容器之外使用這的類,例如用於單元測試,不得不使用 Spring 容器來例項化它,因為沒有其他可能的方法(除了反射)來設定自動裝配的欄位。
為什麼@Resource沒有呢?
在官方文件中,我沒有找到答案,查了一些資料說是:@Autowired 是 Spring 提供的,一旦切換到別的 IoC 框架,就無法支援注入了. 而@Resource 是 JSR-250 提供的,它是 Java 標準,我們使用的 IoC 容器應該和它相容,所以即使換了容器,它也能正常工作。
@Autowired和@Resource推薦用法
1. 什麼場景用什麼合適
記住一句話就行,@Resource傾向於確定性的單一資源,@Autowired為型別去匹配符合此型別所有資源。
如集合注入,@Resource也是可以的,但是建議使用@Autowired。idea左側的小綠標可以看出來,不建議使用@Resource注入集合資源,本質上集合注入不是單一,也是不確定性的。
來自 “ 阿里開發者 ”, 原文作者:汪軍伍(處軒);原文連結:https://mp.weixin.qq.com/s/2zTVFRb9zWEIJDhtzHrCCQ,如有侵權,請聯絡管理員刪除。
相關文章
- 既生 Redis 何生 LevelDB ?Redis
- @Autowired 與@Resource的區別
- @Autowired 和 @ Resource的區別
- @Resource和@Autowired的區別
- @Autowired與@Resource的區別
- @Autowired和@Resource的區別
- @Autowired和@Resource有哪些區別
- Spring5:@Autowired註解、@Resource註解和@Service註解Spring
- 【Java面試】@Resource 和 @Autowired 的區別Java面試
- 聊聊依賴注入註解@Resource和@Autowired依賴注入
- Spring之autowiredSpring
- @Resource,@Autowired,@Inject3種注入方式詳解
- @Resource的作用相當於@Autowired,只不過@Autowired按照byType自動注入
- spring下應用@Resource, @Autowired 和 @Inject註解進行依賴注入的差異Spring依賴注入
- Spring Cloud Alibaba生態探索:Dubbo、Nacos及Sentinel的完美結合SpringCloud
- Spring @Autowired 注入小技巧Spring
- 生產管理諮詢公司 探索 Kaizen方法AI
- Spring Bean 的一生SpringBean
- 每日優鮮市值暴跌,生鮮電商行業何去何從?行業
- Spring Boot 注入介面 @Autowired interfaceSpring Boot
- Spring Autowired(required = false) 說明SpringUIFalse
- 深度探索MMO生態構建——社交系統
- LeSS 的誕生(一):大規模團隊該何去何從
- Spring系列.Resource介面Spring
- 混合雲網路生態的探索與實踐
- 【Java註解用法】@Autowired 與@Resource的區別以及@Qualifier的介紹Java
- 為何google並不青睞招聘名校畢業生Go
- 何時會發生db file sequential read等待事件?事件
- Vue3.2: Ref操作Dom為何既易用又高效?Vue
- Resource Builder 1.1.0 完全破解~~附彙編序號產生器 (10千字)UI
- 如何在 Spring 生態中玩轉 RocketMQ?SpringMQ
- 如何在Spring生態中玩轉RocketMQ?SpringMQ
- 微服務[v1.0.0][Spring生態概述]微服務Spring
- 你必須瞭解Spring的生態Spring
- 探索React Hooks:原來它們是這樣誕生的!ReactHook
- Spring框架裡註解@Autowired的工作原理Spring框架
- 為何我們要用 React 來寫小程式 - Taro 誕生記React
- 軟體架構生態化-多角色交付的探索實踐架構