@Autowired和@Resource的区别是什么?(根据注入对象的类型还是名称来查找容器池中对象注入?)

本文详细解析了Spring框架中@Autowired与@Resource注解的区别及使用方法,包括它们如何在字段与setter方法上应用,以及如何配置Spring以支持这些注解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:wuxinliulei
链接:https://www.zhihu.com/question/39356740/answer/80926247
来源:知乎

@Autowired 与@Resource:
1、@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

2、@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:
@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:
Java代码
@Autowired() @Qualifier("baseDao")    
private BaseDao baseDao;
3、@Resource 是JDK1.6支持的注解默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
<img src="https://pic4.zhimg.com/50/1d434624eb4918db0814529bbcfbc6b7_hd.png" data-rawwidth="201" data-rawheight="392" class="content_image" width="201">
只不过注解处理器我们使用的是Spring提供的,是一样的,无所谓解耦不解耦的说法,两个在便利程度上是等同的。

Java代码
@Resource(name="baseDao")    
private BaseDao baseDao; 
他们的主要区别就是@Autowired是默认按照类型装配的 @Resource默认是按照名称装配的
byName 通过参数名 自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。
byType 通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配
-----------------------------------------------------------------------------------------------------------------------------------------
我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过@Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。
比如下面的beans.xml
package com.wuxinliulei;

public class Boss {
    private Car car;
    private Office office;

    // 省略 get/setter

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}


<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
    <context:annotation-config/> 

    <bean id="boss" class="com.wuxinliulei.Boss"/>
    <bean id="office" class="com.wuxinliulei.Office">
        <property name="officeNo" value="001"/>
    </bean>
    <bean id="car" class="com.wuxinliulei.Car" scope="singleton">
        <property name="brand" value=" 红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>
定义了三个bean对象,但是没有了我们书序的ref指向的内容
比如
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="boss" class="com.wuxinliulei.Boss">
        <property name="car" ref="car"/>
        <property name="office" ref="office" />
    </bean>
    <bean id="office" class="com.wuxinliulei.Office">
        <property name="officeNo" value="002"/>
    </bean>
    <bean id="car" class="com.wuxinliulei.Car" scope="singleton">
        <property name="brand" value=" 红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>

-------------------------------------------------------------------------------------------------------

spring2.5提供了基于注解(Annotation-based)的配置,我们可以通过注解的方式来完成注入依赖。在Java代码中可以使用 @Resource或者@Autowired注解方式来经行注入。虽然@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区 别的。首先来看一下:

a.@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
b.@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
c.@Resource注解是由JDK提供,而@Autowired是由Spring提供
 
@Resource的方式;
d. @Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上

2、使用注解的方式,我们需要修改spring配置文件的头信息,修改部分红色标注,如下

<?xml version="1.0" encoding="UTF-8"?>
<beans http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="Index of /schema/context"
       xsi:schemaLocation="Index of /schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
Index of /schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
               
<context:annotation-config/>
     
</beans>

PS:

----------------------PS开始-------------------------------

在基于主机方式配置Spring的配置文件中,你可能会见到

<context:annotation-config/>

这样一条配置,他的作用是式地向 Spring 容器注册

AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor

这 4 个BeanPostProcessor。

注册这4个BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解。

例如:

如果你想使用@Autowired注解,那么就必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。传统声明方式如下

<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/> 

如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor

<bean class="org.springframework.beans.factory.annotation. CommonAnnotationBeanPostProcessor"/> 

如果想使用@PersistenceContext注解,就必须声明PersistenceAnnotationBeanPostProcessor的Bean。

<bean class="org.springframework.beans.factory.annotation.PersistenceAnnotationBeanPostProcessor"/> 

如果想使用 @Required的注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean。

同样,传统的声明方式如下:

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/> 


一般来说,这些注解我们还是比较常用,尤其是Antowired的注解,在自动注入的时候更是经常使用,所以如果总是需要按照传统的方式一条一条配置显得有些繁琐和没有必要,于是spring给我们提供<context:annotation-config/>的简化配置方式,自动帮你完成声明。

不过,呵呵,我们使用注解一般都会配置扫描包路径选项

<context:component-scan base-package=”XX.XX”/>

该配置项其实也包含了自动注入上述processor的功能,因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。

比如:

<context:component-scan base-package="carPoolingController, carPoolingService, carPoolingDao" />

就把controller包下 service包下 dao包下的注解全部扫描了


----------------------------------------------PS结束------------------------------

3、修改以上配置文件的头信息后,我们就可以在Java代码通过注解方式来注入bean,看下面代码

(1)@Resource

public class StudentService3 implements IStudentService {
    //@Resource(name="studentDao")放在此处也是可行的
    private IStudentDao studentDao;

    private String id;


    public void setId(String id) {
    this.id = id;
    }

@Resource(name="studentDao") // 通过此注解完成从spring配置文件中查找名称为studentDao的bean来装配字段studentDao,如果spring配置文件中不存在 studentDao名称的bean则转向按照bean类型经行查找

public void setStudentDao(IStudentDao studentDao) {
        this.studentDao = studentDao;
}
public void saveStudent() {
        studentDao.saveStudent();
        System.out.print(",ID 为:"+id);
}
}
 

配置文件添加如下信息

<bean id="studentDao" class="com.wch.dao.impl.StudentDao">
</bean>

<bean id="studentService3" class="com.wch.service.impl.StudentService3"></bean>

(2)@Autowired

public class StudentService3 implements IStudentService {
  //@Autowired放在此处也是可行的
  private IStudentDao studentDao;

  private String id;
  
  public void setId(String id) {
       this.id = id;
   }

@Autowired

//通过此注解完成从spring配置文件中 查找满足studentDao类型的bean
//@Qualifier("studentDao")则按照名称经行来查找转配的
 public void setStudentDao(IStudentDao studentDao) {
       this.studentDao = studentDao;
  }


  public void saveStudent() {
       studentDao.saveStudent();
       System.out.print(",ID 为:"+id);
  }
}
 

配置文件添加如下信息

<bean id="studentDao" class="com.wch.dao.impl.StudentDao"></bean>
<bean id="studentService3" class="com.wch.service.impl.StudentService3" />

在java代码中可以使用@Autowire或者@Resource注解方式进行装配,这两个注解的区别是:
@Autowire 默认按照类型装配,默认情况下它要求依赖对象必须存在如果允许为null,可以设置它required属性为false,如果我们想使用按照名称装配,可 以结合@Qualifier注解一起使用;


@Resource默认按照名称装配,当找不到与名称匹配的bean才会按照类型装配,可以通过name属性指定,如果没有指定name属 性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找 依赖对象.

注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖的对象时候,会回退到按照类型装配,但一旦指定了name属性,就只能按照名称 装配了.


--------------------------

当我们在xml里面为类配置注入对象时,会发现xml文件会越来越臃肿,维护起来很麻烦。这时候我们可以使用注解这种机制来为类配置注入对象。

java为我们提供了 javax.annotation.Resource这个注解。

spring框架提供了org.springframework.beans.factory.annotation.Autowired。

一般情况下我们使用 javax.annotation.Resource这个注解,因为这样我们就能实现和spring框架的解藕(不能认同,因为注解处理器还是Spring提供的)。

@Resource可以作用于字段和函数上。当作用于字段上的时候,如果我们只是简单的这样写

@Resource
PersonDao  p;

这时候spring注入p的过程是 1:先查找xml中是否有id为p的元素

2:如果没有找到,则看是否有name属性(@Resource name=“”),有则查找name

3:否则查找PersonDao类型的元素

@Resource可作用于set函数上。

例如:

@Resource
public void setP(PersonDao p) {
  this.p = p;
}

@Autowired注解是根据类型进行查找,比如PersonDao p,他会去xml文件里查找类型为PersonDao的元素

<think>我们正在讨论Spring框架中的两个重要注解:@Autowired@Resource。用户明确询问了它们之间的区别以及使用场景。根据之前的对话历史,用户已经对Spring的依赖注入有了基本了解,现在需要更深入的对比。首先回忆这两个注解的核心区别@Autowired是Spring特有的注解,而@Resource是Java标准注解(JSR-250)。这个根本差异会影响它们的使用方式兼容性。在依赖注入机制上,@Autowired默认按类型匹配。例如当需要注入一个MileageRateService接口时,Spring会查找实现该接口的Bean。如果有多个实现,就需要配合@Qualifier指定名称。而@Resource默认按名称匹配,它先按指定的name属性查找,如果没有指定name则按字段名或属性名查找。使用场景也有差异。@Autowired更灵活,支持required属性设置非强制依赖,还能用在构造器或方法上实现特殊注入逻辑。@Resource则在需要按名称注入时更直观,特别是当存在多个同类型Bean时。考虑用户可能遇到的常见问题:如果同时使用这两个注解注入同名字段会怎样?实际测试表明Spring会优先处理@Resource,因为它的处理顺序更靠前。不过最好避免混用。最后思考如何组织回答结构。先以表格形式清晰对比核心差异,再分别说明典型用法,最后给出选择建议。特别要强调在SpringBoot项目中两者都能用,但团队最好统一风格。</think>### `@Autowired` 与 `@Resource` 的区别及使用场景 在 Spring 依赖注入中,`@Autowired` `@Resource` 是两种核心注解,但它们在来源、注入机制使用场景上存在显著差异。以下是详细对比: | **特性** | **@Autowired** (Spring 特有) | **@Resource** (JSR-250 标准) | |------------------|-------------------------------------------|--------------------------------------| | **来源** | Spring 框架原生注解 | Java 标准注解 (`javax.annotation`) | | **默认注入机制** | **按类型匹配** (byType) | **按名称匹配** (byName) | | **名称指定方式** | 需配合 `@Qualifier("beanName")` | 直接通过 `name` 属性 (`@Resource(name="beanName")`) | | **是否支持构造器注入** | ✅ | ❌ (仅支持字段/Setter方法) | | **是否支持`required`** | ✅ (`@Autowired(required=false)`) | ❌ | | **适用场景** | 优先类型匹配、构造器注入、Spring 生态集成 | 多实现类时精确指定 Bean、跨框架兼容性 | --- #### 一、核心差异详解 1. **注入机制不同** - **@Autowired** 默认按**类型匹配**。例如注入 `MileageRateService` 接口时,Spring 会查找该接口的唯一实现: ```java @Autowired private MileageRateService rateService; // 需确保仅一个实现类 ``` 若存在多个实现,需用 `@Qualifier` 指定: ```java @Autowired @Qualifier("primaryRateService") // 指定 Bean 名称 private MileageRateService rateService; ``` - **@Resource** 默认按**名称匹配**。直接通过字段名或 `name` 属性查找 Bean: ```java @Resource // 匹配名为 "rateService" 的 Bean private MileageRateService rateService; @Resource(name = "backupRateService") // 显式指定名称 private MileageRateService backupService; ``` 2. **依赖处理能力** - **@Autowired** 支持更灵活的注入方式: - **构造器注入**(推荐): ```java @Service public class PaymentService { private final RateService rateService; @Autowired // 可省略(Spring 4.3+) public PaymentService(RateService rateService) { this.rateService = rateService; } } ``` - **集合注入**(自动收集所有实现类): ```java @Autowired private List<RateService> allRateServices; // 注入所有实现类 ``` - **@Resource** 仅支持字段或 Setter 方法注入: ```java @Resource public void setRateService(RateService rateService) { this.rateService = rateService; } ``` 3. **异常处理** - **@Autowired** 默认要求依赖必须存在(`required=true`)。若允许缺失,需显式设置: ```java @Autowired(required = false) // 找不到 Bean 时不报错 private Optional<RateService> optionalRateService; ``` - **@Resource** 找不到 Bean 时**直接抛出异常**,无 `required` 选项。 --- #### 二、使用场景建议 | **场景** | **推荐注解** | **原因** | |------------------------------|-------------------|--------------------------------------| | 精确指定 Bean 名称 | `@Resource` | 直接通过 `name` 属性控制,更简洁 | | 构造器注入 | `@Autowired` | 唯一支持构造器注入的注解 | | 跨框架兼容(如 Jakarta EE) | `@Resource` | Java 标准,非 Spring 项目也可用 | | 按类型自动收集所有实现类 | `@Autowired` | 支持集合注入 (`List<Interface>`) | | 可选依赖(允许为 `null`) | `@Autowired` | 通过 `required=false` 灵活控制 | --- #### 三、最佳实践 1. **Spring Boot 项目** - 优先使用 `@Autowired` + 构造器注入,提升代码可测试性安全性[^1]。 - 多实现类时,用 `@Qualifier` 或 `@Primary` 辅助解决冲突。 2. **兼容性要求高的项目** - 若需兼容非 Spring 容器(如 Jakarta EE),选择 `@Resource`。 3. **避免混用** ```java // ❌ 避免混用(可能导致注入行为混乱) @Autowired @Resource(name = "serviceA") private Service service; ``` > **关键总结**: > - 需要**类型驱动**或**构造器注入** → 选 `@Autowired` > - 需要**精确名称匹配**或**跨框架兼容** → 选 `@Resource` > - 在 Spring 生态中,`@Autowired` 更灵活;在异构环境中,`@Resource` 更通用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值