【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 有什么区别?-阿里云开发者社区

相关推荐
serendipity_hky1 小时前
【微服务 - easy视频 | day01】准备工具+gateway网关及路由至内部服务
java·微服务·架构·gateway·springcloud
生而为虫1 小时前
02.第一个Python程序
开发语言·python
星释2 小时前
Rust 练习册 :Rail Fence Cipher与栅栏密码
开发语言·算法·rust
weixin_441455262 小时前
说说Java有哪些集合类
java·开发语言
合作小小程序员小小店2 小时前
web网页开发,在线%台球俱乐部管理%系统,基于Idea,html,css,jQuery,jsp,java,ssm,mysql。
java·前端·jdk·intellij-idea·jquery·web
李趣趣2 小时前
C#中关于ContextMenuStrip批量添加Item的问题
开发语言·c#
张人玉2 小时前
C# 串口通讯中 SerialPort 类的关键参数和使用方法
开发语言·c#·串口通讯
白山云北诗2 小时前
网站被攻击了怎么办?如何进行DDoS防御?
开发语言·网络安全·php·ddos·防ddos·防cc