在spring中@Resource與@Autowired用法區別

由於之前對@Resource與@Autowired只限於使用,隔久了又忘記了。在此總結此文爲後續開發提高效率。在spring項目中關於Controller層、Service層使用@Resource和@Autowired注入bean使用過程中,有時候@Resource 和 @Autowired可以替換使用;有時,則不可以。爲什麼不可以呢?接下來我們開始通過例子來解答。

1、首先創建一個springmvc的項目,關鍵類代碼如下:

package com.tfq.springaop.service;


/**
 *
 *  @description 汽車接口定義
 *  @author tangfq; 
 *  @version 2020年5月24日 下午12:21:25
 *
 **/

public interface ICar {
	
	/**
	 * 啓動引擎
	 * @return
	 */
	String startEngine();

}

package com.tfq.springaop.service;

import org.springframework.stereotype.Service;


/**
 *
 *  @description 寶馬汽車實現Car接口
 *  @author tangfq; 
 *  @version 2020年5月24日 下午12:24:26
 *
 **/
@Service
public class BwCar implements ICar{

	/* (non-Javadoc)
	 * @see com.tfq.springaop.service.ICar#startEngine()
	 */
	@Override
	public String startEngine() {
		
		return "I am driving bw car";
	}

}

package com.tfq.springaop.controller;

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tfq.springaop.service.ICar;

/**
 *
 *  @description 
 *  @author tangfq; 
 *  @version 2020年5月24日 下午3:35:44
 *
 **/
@RestController
@RequestMapping("/car")
public class CarController {

	@Resource
	private ICar car;
	
	@RequestMapping("/start")
	public String startEngine(){
		return car.startEngine();
	}
	
}

使用@Resource注入名字爲car的bean,但是並沒有名字爲car的bean,這時就會走byType注入, 所以說這個注入成功是根據byType注入成功的,而不是byName。 其實byType就是根據指定的數據類型自動裝配,比如car爲ICar實體類。

訪問項目的CarController結果如下:

2、改動一:

將CarController.java 類中的註解替換爲@Autowired,再次啓動,可以正常訪問,與上圖訪問的結果相同,這裏不再貼圖。這裏是使用@Autowired或@Resource都可以。因爲ICard只有一個bean實體類。通過兩種方式都可以找到注入bean。

查看spring源碼:Autowired的多種方式(spring版本4.2.4.RELEASE)
1.構造器註解(constructor)

2.屬性setter註解

3.field註解

4.配置方法config method

不管使用上面4中的哪個方法,Spring都會滿足聲明的依賴。假如有且只有一個bean匹配依賴的話,那麼這個bean將會被裝配進來。如果有多個bean的話,則用Qualifier指定。

如果沒有匹配的bean,那麼在應用上下文創建的時候,Spring會拋出一個異常。爲了避免異常的出現,可以使用。關於自動裝配詳細參考:https://blog.csdn.net/weixin_43277643/article/details/84253237

3、改動二:

再增加一個實現類BenzCar.java

package com.tfq.springaop.service;

import org.springframework.stereotype.Service;

/**
 *
 *  @description 奔馳汽車
 *  @author tangfq; 
 *  @version 2020年5月24日 下午9:38:00
 *
 **/
@Service
public class BenzCar implements ICar{
	
	@Override
	public String startEngine() {
		return "I am driving Benz car";
	}

}

當把CarController.java的ICar修改爲@Resource修飾,代碼如下:

package com.tfq.springaop.controller;

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tfq.springaop.service.ICar;

/**
 *
 *  @description 
 *  @author tangfq; 
 *  @version 2020年5月24日 下午3:35:44
 *
 **/
@RestController
@RequestMapping("/car")
public class CarController {

	@Resource
	private ICar car;
	
	@RequestMapping("/start")
	public String startEngine(){
		return car.startEngine();
	}
	
}

啓動項目訪問controller,報錯信息:Error creating bean with name 'carController': Injection of resource dependencies failed;No qualifying bean of type [com.tfq.springaop.service.ICar] is defined: expected single matching bean but found 2: benzCar,bwCar.

根據報錯可知在CarController類中,ICar沒有標識bean實現類,有兩個實現類(benzCar、bwCar)不知道取哪一個bean。所以此時要指定一個bean實現類。在ICar上添加如下代碼:

@Resource(name="bwCar")
private ICar car;

或者

@Resource
@Qualifier("bwCar")
private ICar car;

訪問地址:http://localhost:8080/springaop/car/start,結果如下圖:

4、改動三:

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

Could not autowire field: private com.tfq.springaop.service.ICar com.tfq.springaop.controller.CarController.car; nested exception
is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type [com.tfq.springaop.service.ICar] is defined: expected single matching bean but found 2: benzCar,bwCar

根據報錯可知在CarController類中,ICar沒有標識bean實現類,有兩個實現類(benzCar、bwCar)不知道取哪一個bean。

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

@Qualifier修改方式與改動二的相同,依然是修改CarController.java 中間注入的ICar上面

@Autowired
@Qualifier("benzCar")
private ICar car;

@Primary是修飾實現類的,告訴spring,如果有多個實現類時,優先注入被@Primary註解修飾的那個Service。在CarController可以使用@Resource或@Autowired,我們希望注入BwCar.java ,那麼修改BwCar.java爲

package com.tfq.springaop.service;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;


/**
 *
 *  @description 寶馬汽車實現Car接口
 *  @author tangfq; 
 *  @version 2020年5月24日 下午12:24:26
 *
 **/
@Service
@Primary
public class BwCar implements ICar{

	@Override
	public String startEngine() {
		
		return "I am driving bw car";
	}

}


package com.tfq.springaop.controller;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tfq.springaop.service.ICar;

/**
 *
 *  @description 
 *  @author tangfq; 
 *  @version 2020年5月24日 下午3:35:44
 *
 **/
@RestController
@RequestMapping("/car")
public class CarController {

	@Autowired
	private ICar car;
	
	@RequestMapping("/start")
	public String startEngine(){
		return car.startEngine();
	}
	
}

通過以上的例子,他們的相同與不同點如下:

1)共同點

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

 2)不同點

    @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註解一起來修飾。

代碼參考地址:https://blog.csdn.net/magi1201/article/details/82590106?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

深入理解Spring IOC參考地址:https://www.cnblogs.com/chenssy/p/9576769.html

項目下載地址:https://github.com/fuqiangt/project

以上爲我根據網上的介紹然後結合其他blog的內容和評語總結,等後續有時間在寫查看Spring源碼深入理解實現原理。如我表述有誤請大家評論指出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章