面试考察点
- 基础掌握度:面试官不仅仅是想知道这两个注解 "不一样",更是想看你能不能从来源、匹配策略、使用方式等多个维度做系统对比,而不是只背出 "一个是 Spring 的,一个是 JDK 的"。
- 底层原理 :是否理解
@Autowired的 "先类型后名称" 和@Resource的 "先名称后类型" 的匹配机制,以及当存在多个候选 Bean 时各自怎么处理冲突。 - 实践选型:考察你在项目中如何选择这两个注解,是否了解 Spring 官方的推荐做法,以及新版 Spring Boot 中的变化。
核心答案
先上对比表格,一目了然:
| 维度 | @Autowired |
@Resource |
|---|---|---|
| 来源 | Spring 框架(org.springframework.beans.factory.annotation) |
JSR-250 规范(jakarta.annotation / javax.annotation) |
| 匹配策略 | 先按类型(byType) ,有多个再按名称 | 先按名称(byName) ,没找到再按类型 |
| 指定名称 | 配合 @Qualifier("beanName") |
直接 @Resource(name = "beanName") |
| required 属性 | 支持 required = false,注入失败不报错 |
不支持,注入失败直接抛异常 |
| 适用位置 | 构造器、方法、参数、字段 | 方法、字段 |
| 官方推荐 | Spring 官方推荐 | --- |
核心区别就一句话:@Autowired 先类型后名称,@Resource 先名称后类型。
深度解析
一、匹配机制的差异
这是面试官最想听的部分。用一张流程图来对比两者的注入策略:


两个流程图分别展示了两种注解的注入策略,关键区别在于优先级不同:
@Autowired的策略 :Spring 先按类型去容器里找,如果只找到一个,直接注入,皆大欢喜。但如果找到多个同类型的 Bean,Spring 会尝试用字段名去匹配 Bean 名称,匹配上了就用。如果还匹配不上,就得靠@Qualifier显式指定。另外@Autowired支持required = false,允许注入失败时不报错,这在某些可选依赖的场景很有用。@Resource的策略 :正好反过来。它先看有没有指定name,或者直接用字段名当 Bean 名称去容器里找。找到了就注入,找不到才退回按类型查找。但@Resource没有required属性,找不到就报错,没有商量的余地。
二、当存在多个同类型 Bean 时怎么办
这是实际开发中经常遇到的场景。假设你有两个 UserService 的实现:
less
@Service
public class UserServiceImpl implements UserService { }
@Service("vipUserService")
public class VipUserServiceImpl implements UserService { }
用 @Autowired 解决冲突:
less
@Component
public class OrderController {
// 方式一:配合 @Qualifier 指定名称
@Autowired
@Qualifier("vipUserService")
private UserService userService;
// 方式二:字段名恰好是 Bean 名称(Spring 会自动回退到名称匹配)
@Autowired
private UserService vipUserService;
}
用 @Resource 解决冲突:
kotlin
@Component
public class OrderController {
// 直接用 name 属性指定
@Resource(name = "vipUserService")
private UserService userService;
// 或者字段名就是 Bean 名称
@Resource
private UserService vipUserService;
}
对比下来,@Resource 指定名称的方式更直观,不需要额外加一个注解。
三、能加在哪里?
这个点很多人答不全。
java
// @Autowired 能用在这几个地方:
// 1. 字段注入(最常见,但不推荐)
@Autowired
private UserService userService;
// 2. 构造器注入(Spring 官方推荐 ✅)
@Autowired
public OrderController(UserService userService) {
this.userService = userService;
}
// 3. Setter 方法注入
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
// 4. 方法参数(Spring 4.3+,如果只有一个构造器,@Autowired 可省略)
@Resource 只能用在字段和方法上,不能标注在构造器上。这一点面试的时候提一下,能加分。
四、Spring Boot 3.x 的变化
如果你面的是 Spring Boot 3.x / Spring 6.x 的项目,有个变化值得提一嘴:
@Resource 的包路径从 javax.annotation 变成了 jakarta.annotation。因为 Java EE 把命名权交给了 Eclipse 基金会,改名叫 Jakarta EE 了。如果你从 Spring Boot 2.x 升级到 3.x,这个 import 路径得改,不然编译都过不了。
另外,Spring Framework 6.1 / Spring Boot 3.2 之后,核心框架自身的注入不再使用 @Autowired,而是全面转向了构造器注入 + 参数自动检测的模式(不需要任何注解,Spring 自动识别构造器参数类型并注入)。这是一个趋势,面试的时候提一下很加分。
五、生产中到底用哪个?
说实话,两种都行,团队统一就好。但 Spring 官方更推荐用构造器注入 (配合 @Autowired 或不加注解),原因有三:
- 构造器注入能保证依赖不可变(字段可以是
final的) - 依赖关系一目了然,参数太多说明类该拆了
- 方便单元测试,直接传参就行,不用反射
面试高频追问
-
追问一:
@Autowired注入的是接口还是实现类?注入的是接口类型,Spring 容器根据类型找到对应的实现类。面向接口编程,解耦的好处就在这。
-
追问二:构造器注入和字段注入哪个好?为什么?
构造器注入更好。字段注入看起来简洁,但隐藏了依赖关系,而且没法把字段声明为
final。构造器注入让依赖一目了然,也方便做单元测试。 -
追问三:
@Primary注解是干什么的?和@Qualifier有什么区别?@Primary标注在 Bean 上,告诉 Spring "当有多个候选时,优先用我"。它是全局默认选择。@Qualifier是注入点级别的精确指定,优先级更高。一个管全局,一个管局部。
常见面试变体
- "
@Autowired和@Resource的注入方式有什么不同?" - "当有多个同类型 Bean 时,Spring 怎么决定注入哪一个?"
- "Spring 官方推荐哪种依赖注入方式?"
记忆口诀
@Autowired :Spring 家的, 先类型后名称 ,配合 @Qualifier 精确定位。
@Resource :JSR 标准的, 先名称后类型 ,name 属性一步到位。
总结
这两个注解的核心区别就是匹配策略的优先级不同。@Autowired 先类型后名称,@Resource 先名称后类型。面试时把这个区别讲清楚,再提一下构造器注入的优势和 Spring 6.x 的新趋势,这道题稳拿。