在开发 Spring Boot 项目时,我们经常使用 @Autowired 或 @Resource 注解来实现依赖注入。它们看起来功能相似,都能自动装配 Bean,但很多开发者并不清楚两者间的本质差异。今天,我们就来深入剖析一下它们的区别,并探讨在何种场景下应如何选择。
出身不同:Spring 专属 vs Java 标准
首先,从来源上看,这两者有着根本的不同:
@Autowired 是 Spring 框架 原生提供的注解。
@Resource 则来自 Java 官方标准(JSR-250),与 @PostConstruct、@PreDestroy 同属一个规范。
这意味着,如果你未来可能脱离 Spring 生态(例如迁移至标准的 Jakarta EE 环境),@Autowired 将无法使用,而 @Resource 因其标准性,通用性更强。当然,在当前 Spring 一统江湖的背景下,这点差异影响不大,但在理解原理和面试回答时至关重要。
核心机制:Bean查找顺序的差异
这是两者最本质、也最容易引发问题的区别。它们的自动装配遵循不同的查找逻辑。
@Autowired: 类型优先 (byType)
@Autowired 默认采用 按类型(byType) 的方式查找 Bean。
- Spring 首先会在容器中查找与字段(或方法参数)类型匹配的 Bean。
- 如果只找到一个,直接注入成功。
- 如果找到多个同类型的 Bean(例如有多个
UserService 的实现类),Spring 会尝试将字段名作为 Bean 的名称(byName)进行二次匹配。
- 如果名称也无法匹配到唯一 Bean,则会抛出
NoUniqueBeanDefinitionException 异常。
此时,你需要配合 @Qualifier 注解来显式指定要注入的 Bean 名称。
@Autowired
@Qualifier("vipOrderService")
private OrderService orderService;
图1:@Autowired注解的Bean查找逻辑流程图

@Resource: 名称优先 (byName)
@Resource 默认采用 按名称(byName) 的方式查找 Bean。
- 如果不指定任何属性,它会直接用字段名作为 Bean 的名称去容器中查找。
- 如果找到了对应名称的 Bean,则直接注入。
- 如果按名称没找到,它会 回退 到按类型(byType)进行查找。此时如果同类型的 Bean 有多个,同样会报错。
你也可以直接通过其 name 属性来指定 Bean 名称,代码更简洁直观。
// 默认按字段名“orderService”查找
@Resource
private OrderService orderService;
// 显式指定Bean名称
@Resource(name = "premiumOrderService")
private OrderService orderService;
核心记忆点:@Autowired 是 先类型,后名称;@Resource 是 先名称,后类型。这个顺序在多实现类注入时,决定了程序的行为,必须谨慎对待。
图2:@Resource注解的Bean查找逻辑流程图

功能特性对比
虽然都能注入,但在细节功能上,两者并非完全等价。
| 功能 |
@Autowired |
@Resource |
| 可选注入 |
✅ 支持 (required = false) |
❌ 不支持,找不到即报错 |
| 构造器注入 |
✅ 支持(Spring官方推荐方式) |
❌ 不支持 |
| 指定Bean名 |
需配合 @Qualifier |
直接使用 name 属性 |
| 注解简洁度 |
有时需两个注解 |
通常一个注解即可 |
功能详解:
-
可选注入:@Autowired 可以设置为 required = false,当找不到匹配的 Bean 时,会注入 null 而不导致应用启动失败。@Resource 不具备此功能。
@Autowired(required = false)
private OptionalService optionalService; // 允许为null
-
构造器注入:这是当前 Spring 官方推崇的最佳实践,它使依赖关系更明确,便于构造不可变对象,且利于测试。@Autowired 可以用于构造器(Spring 4.3+ 在单个构造器下可省略),而 @Resource 完全不能用于构造器。
@Service
public class OrderService {
private final UserService userService;
// 推荐使用构造器注入
public OrderService(UserService userService) {
this.userService = userService;
}
}
实战选型与避坑指南
那么在实际开发中,我们该如何选择呢?
选型建议:
- 纯 Spring 项目,且使用构造器注入:优先使用
@Autowired 或遵循 Spring 4.3+ 的规则省略注解。
- 需要明确按名称注入:例如配置多数据源、多消息发送器时,使用
@Resource(name = “xxx”) 意图更清晰。
- 老项目或考虑平台通用性:如果项目未来可能脱离 Spring,或本身就是混合框架,使用标准的
@Resource。
- 规避 IDE 误报:在某些情况下(如早期 MyBatis Mapper 注入),IDEA 可能对
@Autowired 报错,可尝试改用 @Resource。
常见“翻车”场景:
-
场景一:多实现类未指定名称
@Component("smsSender")
class SmsNotification implements Notification {}
@Component("emailSender")
class EmailNotification implements Notification {}
@Service
public class AlertService {
@Autowired // 启动报错:找到两个Notification类型的Bean
private Notification notification;
}
解决方案:添加 @Qualifier(“smsSender”) 或改用 @Resource(name = “smsSender”)。
-
场景二:尝试在构造器上使用 @Resource
这是无效的,编译器或运行时会报错。构造器注入请使用 @Autowired 或遵循隐式注入规则。
总结
为了更清晰地对比,我们将核心差异汇总如下:
| 对比项 |
@Autowired |
@Resource |
| 来源 |
Spring 框架 |
Java 标准 (JSR-250) |
| 查找顺序 |
类型 → 名称 |
名称 → 类型 |
| 指定名称 |
需 @Qualifier 配合 |
直接使用 name 属性 |
| 可选注入 |
支持 |
不支持 |
| 构造器注入 |
✅ 支持并推荐 |
❌ 不支持 |
| 通用性 |
Spring 生态内 |
跨容器,更广泛 |
一句话口诀:“类型模糊用 Autowired,名字明确用 Resource。”
希望本文能帮助你彻底理清 @Autowired 和 @Resource 的区别,在未来的 Spring Boot 项目开发中做出更合适的选择。如果你对更多 Java 和 Spring 的底层原理感兴趣,欢迎到 云栈社区 与其他开发者一起交流探讨。

|