在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源码深入理解实现原理。如我表述有误请大家评论指出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值