
@Autowired 的 "先类型后名称" 和 @Resource 的 "先名称后类型" 的匹配机制,以及当存在多个候选 Bean 时各自怎么处理冲突。先上对比表格,一目了然:
维度 | @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 的实现:
@Service
public class UserServiceImpl implements UserService { }
@Service("vipUserService")
public class VipUserServiceImpl implements UserService { }用 @Autowired 解决冲突:
@Component
public class OrderController {
// 方式一:配合 @Qualifier 指定名称
@Autowired
@Qualifier("vipUserService")
private UserService userService;
// 方式二:字段名恰好是 Bean 名称(Spring 会自动回退到名称匹配)
@Autowired
private UserService vipUserService;
}用 @Resource 解决冲突:
@Component
public class OrderController {
// 直接用 name 属性指定
@Resource(name = "vipUserService")
private UserService userService;
// 或者字段名就是 Bean 名称
@Resource
private UserService vipUserService;
}对比下来,@Resource 指定名称的方式更直观,不需要额外加一个注解。
这个点很多人答不全。
// @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 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 的注入方式有什么不同?"@Autowired:Spring 家的,先类型后名称,配合 @Qualifier 精确定位。
@Resource:JSR 标准的,先名称后类型,name 属性一步到位。
这两个注解的核心区别就是匹配策略的优先级不同。@Autowired 先类型后名称,@Resource 先名称后类型。面试时把这个区别讲清楚,再提一下构造器注入的优势和 Spring 6.x 的新趋势,这道题稳拿。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。