@Autowired和@Resource到底有什么区别

@Autowired和@Resource都是Spring中用于依赖注入的注解,但来源、查找顺序、支持参数、依赖注入方式及IDE提示有所不同。@Autowired来自Spring,按类型->名称查找,只支持required参数;@Resource来自JSR-250,按名称->类型查找,支持更多参数,并且仅在构造方法注入时会有问题。

@Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同,并且这也是常见的面试题之一,所以我们今天就来盘它。 @Autowired 和 @Resource 的区别主要体现在以下 5 点:

  1. 来源不同;
  2. 依赖查找的顺序不同;
  3. 支持的参数不同;
  4. 依赖注入的用法不同;
  5. 编译器 IDEA 的提示不同。

1.来源不同

@Autowired 和 @Resource 来自不同的“父类”,其中 @Autowired 是 Spring 定义的注解,而 @Resource 是 Java 定义的注解,它来自于 JSR-250(Java 250 规范提案)。

小知识:JSR 是 Java Specification Requests 的缩写,意思是“Java 规范提案”。任何人都可以提交 JSR 给 Java 官方,但只有最终确定的 JSR,才会以 JSR-XXX 的格式发布,如 JSR-250,而被发布的 JSR 就可以看作是 Java 语言的规范或标准。

2.依赖查找顺序不同

依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。而查找有分为两种实现:按名称(byName)查找或按类型(byType)查找,其中 @Autowired 和 @Resource 都是既使用了名称查找又使用了类型查找,但二者进行查找的顺序却截然相反。

2.1 @Autowired 查找顺序

@Autowired 是先根据类型(byType)查找,如果存在多个 Bean 再根据名称(byName)进行查找,它的具体查找流程如下:

关于以上流程,可以通过查看 Spring 源码中的 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 实现分析得出,源码执行流程如下图所示:

2.2 @Resource 查找顺序

@Resource 是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找,它的具体流程如下图所示:

关于以上流程可以在 Spring 源码的 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessPropertyValues 中分析得出。虽然 @Resource 是 JSR-250 定义的,但是由 Spring 提供了具体实现,它的源码实现如下:

2.3 查找顺序小结

由上面的分析可以得出:

  • @Autowired 先根据类型(byType)查找,如果存在多个(Bean)再根据名称(byName)进行查找;
  • @Resource 先根据名称(byName)查找,如果(根据名称)查找不到,再根据类型(byType)进行查找。

3.支持的参数不同

@Autowired 和 @Resource 在使用时都可以设置参数,比如给 @Resource 注解设置 name 和 type 参数,实现代码如下:

@Resource(name = "userinfo", type = UserInfo.class)
private UserInfo user;
复制代码

二者支持的参数以及参数的个数完全不同,其中 @Autowired 只支持设置一个 required 的参数,而 @Resource 支持 7 个参数,支持的参数如下图所示:

4.依赖注入的支持不同

@Autowired 和 @Resource 支持依赖注入的用法不同,常见依赖注入有以下 3 种实现:

  1. 属性注入
  2. 构造方法注入
  3. Setter 注入

这 3 种实现注入的实现代码如下。

a) 属性注入

@RestController
public class UserController {
    // 属性注入
    @Autowired
    private UserService userService;

    @RequestMapping("/add")
    public UserInfo add(String username, String password) {
        return userService.add(username, password);
    }
}
复制代码

b) 构造方法注入

@RestController
public class UserController {
    // 构造方法注入
    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping("/add")
    public UserInfo add(String username, String password) {
        return userService.add(username, password);
    }
}
复制代码

c) Setter 注入

@RestController
public class UserController {
    // Setter 注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping("/add")
    public UserInfo add(String username, String password) {
        return userService.add(username, password);
    }
}
复制代码

其中, @Autowired 支持属性注入、构造方法注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入,当使用 @Resource 实现构造方法注入时就会提示以下错误:

5.编译器提示不同

当使用 IDEA 专业版在编写依赖注入的代码时,如果注入的是 Mapper 对象,那么使用 @Autowired 编译器会提示报错信息,报错内容如下图所示:

虽然 IDEA 会出现报错信息,但程序是可以正常执行的。 然后,我们再将依赖注入的注解更改为 @Resource 就不会出现报错信息了,具体实现如下:

总结

@Autowired 和 @Resource 都是用来实现依赖注入的注解(在 Spring/Spring Boot 项目中),但二者却有着 5 点不同:

  1. 来源不同:@Autowired 来自 Spring 框架,而 @Resource 来自于(Java)JSR-250;
  2. 依赖查找的顺序不同:@Autowired 先根据类型再根据名称查询,而 @Resource 先根据名称再根据类型查询;
  3. 支持的参数不同:@Autowired 只支持设置 1 个参数,而 @Resource 支持设置 7 个参数;
  4. 依赖注入的用法支持不同:@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入;
  5. 编译器 IDEA 的提示不同:当注入 Mapper 对象时,使用 @Autowired 注解编译器会提示错误,而使用 @Resource 注解则不会提示错误。
<think>我们正在讨论Spring框架中的两个重要注解@Autowired@Resource。用户明确询问了它们之间的区别以及使用场景。根据之前的对话历史,用户已经对Spring的依赖注入有了基本了解,现在需要更深入的对比。首先回忆这两个注解的核心区别@AutowiredSpring特有的注解,而@ResourceJava标准注解(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` 更通用。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值