03.07 SpringBoot中,@Autowired和@Resource使用起來到底有什麼區別?

lucky小默


spring中,@Resource和@Autowired都是做bean的注入時使用。使用過程中,有時候@Resource 和 @Autowired可以替換使用;有時,則不可以。

下面,根據自己的學習,整理下這兩個註解使用中的共同點和不同點,及用法上的不同。

共同點

@Resource和@Autowired都可以作為注入屬性的修飾,在接口僅有單一實現類時,兩個註解的修飾效果相同,可以互相替換,不影響使用。

不同點

@Resource是Java自己的註解,@Resource有兩個屬性是比較重要的,分是name和type;Spring將@Resource註解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機制使用byName自動注入策略。

@Autowired是spring的註解,是spring2.5版本引入的,Autowired只根據type進行注入,不會去匹配name。如果涉及到type無法辨別注入對象時,那需要依賴@Qualifier或@Primary註解一起來修飾。

我們創建一個簡單的springboot項目demo,

定義一個接口Human.java,裡面一個方法 runMarathon,

一個實現類Man.java

一個Controller類HumanController.java,裡面注入Human接口的實現

附各Java類源碼

package com.example.annotation.service;

/**

* service接口定義

* @author Administrator

*/

public interface Human {

/**

* 跑馬拉松

* @return

*/

String runMarathon();

}

package com.example.annotation.service.impl;

import com.example.annotation.service.Human;

import org.springframework.stereotype.Service;

/**

* service接口第一實現類

* @author Administrator

*/

@Service

public class Man implements Human {

public String runMarathon() {

return "A man run marathon";

}

}

package com.example.annotation.controller;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import com.example.annotation.service.Human;

/**

* controller層實現類

* @author Administrator

*/

@RestController

@RequestMapping("/an")

public class HumanController {

@Resource

private Human human;

@RequestMapping("/run")

public String runMarathon() {

return human.runMarathon();

}

}

至此,代碼整理完成,啟動springboot,瀏覽器地址欄輸入http://localhost:8080/an/run

改動一:

將HumanController.java 類中的註解替換為@Autowired,再次啟動,可以正常訪問,與上圖相同,這裡不再貼訪問結果圖。

改動二:

再增加一個實現類Woman.java

package com.example.annotation.service.impl;

import com.example.annotation.service.Human;

import org.springframework.stereotype.Service;

/**

* service接口第二實現類

* @author Administrator

*/

@Service

public class Woman implements Human {

public String runMarathon() {

return "An woman run marathon";

}

}

HumanController.java 註解使用@Resource

@Resource

private Human human;

啟動springboot,控制檯會報錯,報錯信息太多,截取關鍵信息

2018-09-10 16:07:10.362 WARN 5592 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'humanController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.annotation.service.Human' available: expected single matching bean but found 2: man,woman

找關鍵信息 expected single matching bean but found 2: man,woman,被期望的單一結果被匹配到兩個結果man和woman。

這裡,我們需要藉助@Resource註解的name屬性或@Qualifier來確定一個合格的實現類

代碼修改為

@Resource(name="woman")

private Human human;

@Resource

@Qualifier("woman")

private Human human;

上面,我們指定了Human接口的實現類是Woman.java,啟動springboot,訪問 http://localhost:8080/an/run

改動三:

在改動二的基礎上,將註解替換為@Autowired,啟動報錯

Description:

Field human in com.example.annotation.controller.HumanController required a single bean, but 2 were found:

- man: defined in file [D:\\DEV_ENV\\springbootws\\annotation\\target\\classes\\com\\example\\annotation\\service\\impl\\Man.class]

- woman: defined in file [D:\\DEV_ENV\\springbootws\\annotation\\target\\classes\\com\\example\\annotation\\service\\impl\\Woman.class]

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

報錯信息很明顯,HumanController需要一個bean實現,但是找到了兩個 man 和woman

解決方案:使用@Primary註解,在有多個實現bean時告訴spring首先@Primary修飾的那個;或者使用@Qualifier來標註需要注入的類。

@Qualifier修改方式與改動二的相同,依然是修改HumanController.java 中間注入的Human上面,這裡不再複述

@Primary是修飾實現類的,告訴spring,如果有多個實現類時,優先注入被@Primary註解修飾的那個。這裡,我們希望注入Man.java ,那麼修改Man.java為

package com.example.annotation.service.impl;

import org.springframework.context.annotation.Primary;

import org.springframework.stereotype.Service;

import com.example.annotation.service.Human;

/**

* service接口第一實現類

* @author Administrator

*/

@Service

@Primary

public class Man implements Human {

public String runMarathon() {

return "A man run marathon";

}

}

啟動springboot後,可以看到注入的已經是Man.java 了。


Java架構達人



一、共同的用途

做bean的注入時使用

裝配bean. 寫在字段上,或寫在setter方法


二、不同點


@Autowired

屬於Spring的註解             org.springframework.beans.factory.annotation.Autowired

@Autowired 默認按類型裝配,依賴對象必須存在,如果要允許null值,可以設置它的required屬性為false @Autowired(required=false),也可以使用名稱裝配,配合@Qualifier註解


@Resource 

不屬於Spring的註解,JDK1.6支持的註解    javax.annotation.Resource

@Resource 默認按名稱進行裝配,通過name屬性進行指定


三、總結

@Autowired自動註解,舉個例子吧,一個類,倆個實現類,Autowired就不知道注入哪一個實現類。

Resource有name屬性,可以區分。


分享到:


相關文章: