@Autowired和@Resource到底什么區(qū)別,你明白了嗎?
阿粉相信,大家做 Java 開發(fā)的,肯定對(duì)于 Spring 是非常熟悉的,而且面試的時(shí)候,也相信大家能夠非常輕易的知道這個(gè)所有的關(guān)于 Spring 的面試題,比如 Spring 的注入什么的。也肯定會(huì)被問到 @Autowired 和 @Resource 到底用哪個(gè)比較適合,今天阿粉就來講講這個(gè)注入的注解是個(gè)什么區(qū)別。
@Autowired
@Autowired顧名思義,就是自動(dòng)裝配,而它的作用是為了消除代碼Java代碼里面的 getter/setter 與 bean 屬性中的 property 。
當(dāng)然,getter看個(gè)人需求,如果私有屬性需要對(duì)外提供的話,應(yīng)當(dāng)予以保留。
也有很多面試官喜歡詢問,Spring 的自動(dòng)裝配你了解么?其實(shí)問的也是這個(gè)注解,而這個(gè)注解中有幾個(gè)屬性,需要大家知道。
- no
默認(rèn)值,表示不使用自動(dòng)裝配,Bean 依賴必須通過 ref 元素定義。
- byName
根據(jù) Property 的 name 自動(dòng)裝配,如果一個(gè) Bean 的 name 和另一個(gè) Bean 中的 Property 的 name 相同,則自動(dòng)裝配這個(gè) Bean 到 Property 中。(表示按屬性名稱自動(dòng)裝配,XML 文件中 Bean 的 id 必須與類中的屬性名稱相同)
- byType
根據(jù) Property 的數(shù)據(jù)類型(Type)自動(dòng)裝配,如果一個(gè) Bean 的數(shù)據(jù)類型兼容另一個(gè) Bean 中 Property 的數(shù)據(jù)類型,則自動(dòng)裝配。(XML 文件中 Bean 的 id 與類中的屬性名稱可以不同,但必須只有一個(gè)類型的 Bean。)
- constructor
類似于 byType,根據(jù)構(gòu)造方法參數(shù)的數(shù)據(jù)類型,進(jìn)行 byType 模式的自動(dòng)裝配。(類中構(gòu)造函數(shù)的參數(shù)必須在配置文件中有相同的類型)
- autodetect(3.0版本不支持)
如果 Bean 中有默認(rèn)的構(gòu)造方法,則用 constructor 模式,否則用 byType 模式。
其實(shí)這些參數(shù)都指明了一件事情,這個(gè) @Autowired 的注解,就是根據(jù) type 也就是類型來進(jìn)行裝配,與之而來的就是 @Resource 他又是什么呢?
@Resource
官方描述為,一般用在類屬性或者setter方法上聲明屬性需要自動(dòng)裝配。
如果在Resource注解中指定了bean的名稱,則Spring會(huì)只按注解中的bame屬性查找合適對(duì)象,然后進(jìn)行裝配。如果注解中沒有指定名稱,先按類屬性的變量名查找,如果還是未找到,則按類型進(jìn)行查找。
它的內(nèi)部也有屬性:
- name
定義了name屬性的值, 就只按照name值匹配,使用byName的自動(dòng)注入策略
- type
定義了type屬性的值, 就只按照type值匹配,使用byType的自動(dòng)注入策略
如果你不指定的話,他自己會(huì)默認(rèn)使用反射機(jī)制,使用byName自動(dòng)注入策略。
那么面試官的問題就來了,@Autowired 和 @Resource 的區(qū)別在哪呢?什么時(shí)候選擇用什么才合適呢?
@Autowired 和 @Resource 的區(qū)別
1.包就不一樣
@Autowired 是Spring提供的。
@Resource 是J2EE提供的。也就是Java規(guī)范的。
2.裝配的默認(rèn)類型不一樣
@Autowired只按type裝配。
@Resource默認(rèn)是按name裝配。
@Autowired默認(rèn)按類型裝配,默認(rèn)情況下必須要求依賴對(duì)象存在,如果要允許null值,可以設(shè)置它的required屬性為false。
如果想使用名稱裝配可以結(jié)合@Qualifier注解進(jìn)行使用。
而默認(rèn)按照名稱進(jìn)行裝配,名稱可以通過name屬性進(jìn)行指定,如果沒有指定name屬性,當(dāng)注解寫在字段上時(shí),默認(rèn)取字段名進(jìn)行名稱查找。
如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配。當(dāng)找不到與名稱匹配的bean時(shí)才按照類型進(jìn)行裝配。但是需要注意的是,如果name屬性一旦指定,就只會(huì)按照名稱進(jìn)行裝配。
那么我們選擇哪一種最好呢?
其實(shí)大家在開發(fā)的時(shí)候,有沒有注意到一個(gè)地方,就是 IDEA 有時(shí)候還會(huì)在 @Autowired 注解上面Field injection is not recommended (字段注入是不被推薦的)這個(gè)警告,雖然并不屬于報(bào)錯(cuò),但是確實(shí)是警告的存在。但是 @Resource 就不會(huì)呢?
其實(shí)有很多人也說不上來為啥,阿粉個(gè)人感覺,@Autowired是Spring提供的,它是特定IoC提供的特定注解,這就導(dǎo)致了應(yīng)用與框架的強(qiáng)綁定,一旦換用了其他的IoC框架,是不能夠支持注入的。
而 @Resource是 Java 自己提供的,它是Java標(biāo)準(zhǔn),我們使用的IoC容器應(yīng)當(dāng)去兼容它,這樣即使更換容器,也可以正常工作。
那么為什么還有這么多的人使用的都是 @Autowired 注解呢?
那就只有兩個(gè)字了,簡(jiǎn)單,使用構(gòu)造器或者setter注入需要寫更多業(yè)務(wù)無關(guān)的代碼,十分麻煩,而字段注入大幅簡(jiǎn)化了它們。并且絕大多數(shù)情況下業(yè)務(wù)代碼和框架就是強(qiáng)綁定的,完全松耦合只是一件理想上的事,犧牲了敏捷度去過度追求松耦合反而得不償失。
所以,你知道他們的區(qū)別是什么了么?