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

相关推荐
我今晚不熬夜6 小时前
Java语言实现Modbus协议通过用串口读取数据(以RTU为例)
java·网络协议
小锋java12347 小时前
Maven 4 要来了:15 年后,Java 构建工具迎来"彻底重构"
java·maven
卓怡学长7 小时前
w269基于spring boot + vue 候鸟监测数据管理系统
java·数据库·spring boot·spring·intellij-idea
孫治AllenSun7 小时前
【MDC】使用 MDC 封装一个 LogMdcUtil 工具类
java·spring boot·后端
济*沧*海7 小时前
BaseMapper的介绍
java·windows·tomcat
李燚7 小时前
Go 项目怎么组织:DDD 4 层 vs MVC vs 脚本式
开发语言·golang·mvc·ddd·agent框架·eino
plainGeekDev7 小时前
依赖管理 → Version Catalog
android·java·kotlin
2zcode8 小时前
免费开源项目文档:基于MATLAB图像处理的啤酒瓶口缺陷检测系统设计与实现
开发语言·图像处理·matlab
人工智能时代 准备好了吗8 小时前
AI回答内容进入率监测:引用识别、文本匹配与语义判断
开发语言·人工智能·python
LONGZETECH8 小时前
新能源汽车动力电池检测仿真教学系统:C/S 分层架构与数字化实训落地全解析
大数据·c语言·开发语言·人工智能·架构·系统架构·汽车