@Autowired 和 @Resource 都是 Spring/Spring Boot 項目中,用來進(jìn)行依賴注入的注解。它們都提供了將依賴對象注入到當(dāng)前對象的功能,但二者卻有眾多不同。 @Autowired 和 @Resource 的區(qū)別主要體現(xiàn)在以下:
1.來源不同
@Autowired 是 Spring 定義的注解,而 @Resource 是 Java 定義的注解(JDK自帶),它來自于JSR-250(Java 250 規(guī)范提案)
2.依賴查找順序不同
依賴注入的功能,是通過先在 Spring IoC 容器中查找對象,再將對象注入引入到當(dāng)前類中。而查找有分為兩種實(shí)現(xiàn):按名稱(byName)查找或按類型(byType)查找,其中 @Autowired 和 @Resource 都是既使用了名稱查找又使用了類型查找,但二者進(jìn)行查找的順序卻截然相反。
2.1 @Autowired 查找順序
@Autowired 是先根據(jù)類型(byType)查找,如果存在多個 Bean 再根據(jù)名稱(byName)進(jìn)行查找,它的具體查找流程如下:

2.2 @Resource 查找順序
@Resource 是先根據(jù)名稱查找,如果(根據(jù)名稱)查找不到,再根據(jù)類型進(jìn)行查找,它的具體流程如下圖所示:

2.3 查找順序小結(jié)
- @Autowired 先根據(jù)類型(byType)查找,如果存在多個(Bean)再根據(jù)名稱(byName)進(jìn)行查找
- @Resource 先根據(jù)名稱(byName)查找,如果(根據(jù)名稱)查找不到,再根據(jù)類型(byType)進(jìn)行查找
3.支持的參數(shù)不同
@Autowired只包含一個參數(shù):required,表示是否開啟自動注入,默認(rèn)是true,要求依賴對象必須存在,如果要允許null值,可以設(shè)置為false

@Resource包含七個參數(shù),其中最重要的兩個參數(shù)是:name 和 type

如果沒有指定name屬性,當(dāng)注解寫在字段上時,默認(rèn)取字段名,按照名稱查找。
當(dāng)注解標(biāo)注在屬性的setter方法上,即默認(rèn)取屬性名作為bean名稱尋找依賴對象。
當(dāng)找不到與名稱匹配的bean時才按照類型進(jìn)行裝配。但是需要注意的是,如果name屬性一旦指定,就只會按照名稱進(jìn)行裝配。
如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進(jìn)行裝配,找不到則拋出異常
如果指定了name,則從上下文中查找名稱(id)匹配的bean進(jìn)行裝配,找不到則拋出異常
如果指定了type,則從上下文中找到類型匹配的唯一bean進(jìn)行裝配,找不到或者找到多個,都會拋出異常
如果既沒有指定name,又沒有指定type,則自動按照byName方式進(jìn)行裝配;如果沒有匹配,則回退為一個原始類型進(jìn)行匹配,如果匹配則自動裝配;
4.支持依賴注入的用法不同(作用域不同)
- @Autowired 可以作用在construct,field,setter方法(可以有多個參數(shù),并且參數(shù)上可以使用@Qualifies進(jìn)行標(biāo)注)
- @Resource 只可以使用在field,setter方法上(只能是單個單數(shù)的setter方法)
舉栗子
- 屬性注入
@Autowired private RedisTemplate redisTemplate; @Resource private RedisTemplate redisTemplate;
- set 方法注入
private RedisTemplate redisTemplate; @Autowired public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Resource public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; }2.2.3 構(gòu)造方法注入(@Resource 不支持構(gòu)造方法注入)
private RedisTemplate redisTemplate; @Autowired //Spring4.3+之后,constructor注入 支持非顯示注入方式,也就是說可以不寫>這個注解 public AdminServiceImpl(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; }
5.編譯器提示不同
使用 @Autowired時,如果注入的是 Mapper 對象編譯器會提示報錯信息且注解上有優(yōu)化提示(還是可以使用滴,只是編譯器不推薦而已)。注入對象非 Mapper 時不會有報錯信息,但是注解上優(yōu)化提示還在

使用@Resource 則不會出現(xiàn)上面的問題

最后我們說說什么時候用@Autowired,什么時候用@Resource
1.當(dāng)一個接口類 Service 只有一個實(shí)現(xiàn)類 ServiceImpl 時,兩者都差不多,但是使用 @Resource 不會有難看的提示
2.當(dāng)一個接口類 Service 有多個實(shí)現(xiàn)類 ServiceImpl 時(多態(tài))
僅僅使用 @Autowired 會報錯,因為它不知道去實(shí)現(xiàn)哪一個,需要結(jié)合 @Qualifier 來確定使用哪個實(shí)現(xiàn)類,雖然這樣可以解決錯誤,但是引起了效率低下
企業(yè)微信截圖_16811178016045.png使用 @Resource 沒有任何參數(shù)時也會報錯,但是可以通過使用參數(shù) name 來確定使用哪個實(shí)現(xiàn)類,從而解決這個問題
企業(yè)微信截圖_16811169481325.png

