【Java】Java 中 @Resource 与 @Autowired 的区别详解


文章目录

    • 一、前言
    • 二、两者的来源与定位
    • 三、共同点
    • [四、`@Autowired` 注入机制详解](#四、@Autowired 注入机制详解)
      • [1. 按类型注入(byType)](#1. 按类型注入(byType))
      • [2. 当有多个同类型 Bean 时](#2. 当有多个同类型 Bean 时)
      • [3. 解决方案](#3. 解决方案)
        • [(1)使用 `@Qualifier` 指定 Bean 名称:](#(1)使用 @Qualifier 指定 Bean 名称:)
        • [(2)使用 `@Primary` 标记优先 Bean:](#(2)使用 @Primary 标记优先 Bean:)
      • [4. 支持构造器注入、Setter 注入、字段注入](#4. 支持构造器注入、Setter 注入、字段注入)
      • [5. 支持 `required` 属性](#5. 支持 required 属性)
    • [五、`@Resource` 注入机制详解](#五、@Resource 注入机制详解)
      • [1. 按名称注入(byName)](#1. 按名称注入(byName))
      • [2. 若找不到匹配名称,则按类型注入(byType)](#2. 若找不到匹配名称,则按类型注入(byType))
      • [3. 可通过属性显式指定 Bean 名称](#3. 可通过属性显式指定 Bean 名称)
      • [4. 不支持 `@Primary` 和 `@Qualifier`](#4. 不支持 @Primary@Qualifier)
    • 六、注入顺序对比(核心差异)
    • [七、在 Spring Boot 中的推荐实践](#七、在 Spring Boot 中的推荐实践)
    • 八、实践建议

一、前言

在 Spring 开发中,依赖注入(Dependency Injection, DI) 是最核心的特性之一。

当我们要把一个 Bean 自动注入到另一个类中时,经常会看到两种注解:

java 复制代码
@Autowired
private UserService userService;
java 复制代码
@Resource
private UserService userService;

它们看起来效果相同,但实际上存在底层机制与使用细节的差异

下面将深入剖析两者的区别与最佳实践。


二、两者的来源与定位

注解 所属包 引入规范 依赖容器
@Autowired org.springframework.beans.factory.annotation Spring 框架 Spring
@Resource jakarta.annotation(或旧版 javax.annotation JSR-250 标准 Java EE(兼容 Spring)

简而言之:

  • @AutowiredSpring 专属注解
  • @ResourceJava 官方标准注解

💡 Spring 同时支持两者,但其注入规则不同。


三、共同点

在功能层面,它们都用于实现 依赖自动注入 (即不再手动 new 对象)。

示例:

java 复制代码
@Service
public class OrderService {

    @Autowired
    private UserService userService;

    public void createOrder() {
        userService.notifyUser();
    }
}

或使用 @Resource

java 复制代码
@Service
public class OrderService {

    @Resource
    private UserService userService;

    public void createOrder() {
        userService.notifyUser();
    }
}

两种方式都能正常工作。

但区别在于:当容器中存在多个同类型 Bean 时,它们的注入逻辑完全不同。


四、@Autowired 注入机制详解

1. 按类型注入(byType)

Spring 会优先根据 类型(Type) 查找匹配的 Bean:

java 复制代码
@Autowired
private UserService userService;

如果容器中存在唯一的 UserService 类型 Bean,就能正常注入。


2. 当有多个同类型 Bean 时

java 复制代码
@Service
public class UserServiceA implements UserService {}

@Service
public class UserServiceB implements UserService {}

@Autowired
private UserService userService; // ❌ 报错:NoUniqueBeanDefinitionException

此时 Spring 不知道该注入哪一个。


3. 解决方案

(1)使用 @Qualifier 指定 Bean 名称:
java 复制代码
@Autowired
@Qualifier("userServiceA")
private UserService userService;

(2)使用 @Primary 标记优先 Bean:
java 复制代码
@Service
@Primary
public class UserServiceA implements UserService {}

4. 支持构造器注入、Setter 注入、字段注入

java 复制代码
@Autowired
public OrderService(UserService userService) {
    this.userService = userService;
}

或:

java 复制代码
@Autowired
public void setUserService(UserService userService) {
    this.userService = userService;
}

推荐使用 构造器注入 ------ 更利于单元测试与不可变设计。


5. 支持 required 属性

java 复制代码
@Autowired(required = false)
private UserService userService;

如果容器中没有该 Bean,不会抛异常,而是注入 null


五、@Resource 注入机制详解

1. 按名称注入(byName)

@Resource 默认优先根据 字段名(Name) 查找 Bean。

java 复制代码
@Resource
private UserService userService;

Spring 会首先尝试匹配 Bean 名称为 "userService" 的对象。


2. 若找不到匹配名称,则按类型注入(byType)

如果容器中没有 "userService" 这个 Bean 名称,Spring 会退而求其次,按类型注入。

⚠️ 若存在多个相同类型 Bean,会抛出 NoUniqueBeanDefinitionException


3. 可通过属性显式指定 Bean 名称

java 复制代码
@Resource(name = "userServiceA")
private UserService userService;

这相当于 @Autowired + @Qualifier("userServiceA")


4. 不支持 @Primary@Qualifier

@Resource 是 Java 标准注解,不依赖 Spring 的扩展机制,因此不支持这两个注解。


六、注入顺序对比(核心差异)

步骤 @Autowired @Resource
默认策略 按类型注入(byType) 按名称注入(byName)
是否支持 @Qualifier ✅ 支持 ❌ 不支持
是否支持 @Primary ✅ 支持 ❌ 不支持
是否可设置 required ✅ 可选 ❌ 无此属性
是否依赖 Spring 框架 ✅ 是 ❌ 否(标准注解)
优先查找 类型 → 名称 名称 → 类型
使用包 org.springframework.beans.factory.annotation jakarta.annotation
常见错误 多个同类型 Bean 报错 名称不匹配时报错

七、在 Spring Boot 中的推荐实践

场景 推荐注解 理由
纯 Spring 项目 @Autowired Spring 原生,功能更强
兼容 Jakarta / JavaEE 项目 @Resource 标准化,跨框架通用
有多个 Bean 需区分时 @Autowired + @Qualifier 精确控制
惰性加载或选填依赖 @Autowired(required = false) 更灵活

💡 Spring 官方文档推荐优先使用 @Autowired,除非需要兼容性或与非 Spring 框架交互。



八、实践建议

  1. 优先使用 @Autowired(尤其在 Spring Boot 项目中);
  2. 当需要按名称注入时,使用:
java 复制代码
@Autowired
@Qualifier("beanName")
  1. 若项目需要兼容 Jakarta EE 或第三方容器,可使用:
java 复制代码
@Resource(name = "beanName")
  1. 避免在同一个项目中混用两者,以保持一致性;
  2. 推荐使用 构造器注入,提高可测试性与代码可维护性。

参考资料

面试突击78:@Autowired 和 @Resource 有什么区别?-阿里云开发者社区

相关推荐
一勺菠萝丶7 分钟前
PDF24 转图片出现“中间横线”的根本原因与终极解决方案(DPI 原理详解)
java
姓蔡小朋友11 分钟前
Unsafe类
java
一只专注api接口开发的技术猿24 分钟前
如何处理淘宝 API 的请求限流与数据缓存策略
java·大数据·开发语言·数据库·spring
superman超哥25 分钟前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
荒诞硬汉25 分钟前
对象数组.
java·数据结构
期待のcode27 分钟前
Java虚拟机的非堆内存
java·开发语言·jvm
黎雁·泠崖27 分钟前
Java入门篇之吃透基础语法(二):变量全解析(进制+数据类型+键盘录入)
java·开发语言·intellij-idea·intellij idea
仙俊红30 分钟前
LeetCode484周赛T4
java