不用死记硬背,一看就懂! 核心结论:
- @Autowired:Spring 框架专属注解,默认按类型(byType)匹配,找不到对应类型直接报错;若想按名字匹配,必须搭配
@Qualifier注解使用。 - @Resource:Java 官方标准注解(遵循JSR-250规范),默认按名字(byName)匹配,名字匹配失败后,会自动降级按类型匹配,无需额外注解。
一、核心场景:给「水杯」找「水」
为了更直观理解,我们模拟一个真实开发场景:假设你有一个水杯类(Cup) ,需要注入水(Water) ,但此时系统中存在两个水的实现类,具体代码如下:
// 水的接口(定义水的统一规范)
public interface Water {}
// 实现类1:热水(Bean名称为hotWater)
@Component("hotWater")
public class HotWater implements Water {}
// 实现类2:冷水(Bean名称为coldWater)
@Component("coldWater")
public class ColdWater implements Water {}
现在要给Cup类注入Water实例,@Autowired和@Resource的查找逻辑完全不同,我们一步步拆解👇
二、@Autowired 可视化图解(先看类型,再看名字)
查找逻辑:类型优先 → 同名辅助
用生活场景类比:就像你跟服务员说:「给我一杯【水】,不管冷热,只要是水就行」,服务员会先找所有“水”类的饮品,再判断怎么给你。
- Spring容器先查找所有实现了
Water接口的Bean(即所有“水”); - 最终找到2个匹配的Bean:hotWater(热水)、coldWater(冷水);
- Spring会直接报错:NoUniqueBeanDefinitionException(找到两个符合类型的Bean,无法确定注入哪一个)。
代码示例(无@Qualifier,直接报错)
@Component
public class Cup {
// 报错:NoUniqueBeanDefinitionException(找到2个Water类型Bean,无法选择)
@Autowired
private Water water;
}
想指定具体注入哪个?必须加 @Qualifier
如果想明确注入热水(hotWater),需要在@Autowired后搭配@Qualifier注解,指定Bean的名字,精准匹配:
@Component
public class Cup {
// 先按类型找Water,再按@Qualifier指定的名字hotWater精准匹配
@Autowired
@Qualifier("hotWater")
private Water water;
}
可视化总结
@Autowired 查找流程:
【找类型】→ 只找到1个 → 直接注入
【找类型】→ 找到多个 → 报错
【找类型】+ @Qualifier → 精准匹配名字,成功注入
三、@Resource 可视化图解(先看名字,再看类型)
查找逻辑:名字优先 → 类型兜底
还是用生活场景类比:就像你跟服务员说:「给我一杯【名字叫hotWater的水】」,服务员会先精准找这个名字的饮品,找不到再找同类。
- Spring容器先查找名字完全匹配的Bean(优先匹配@Resource的name属性);
- 找到名字为
hotWater的Bean,直接注入,无需额外操作,完美匹配!
代码示例(最简单,不用额外注解)
@Component
public class Cup {
// 直接按name属性匹配hotWater,一步到位,无需额外注解
@Resource(name = "hotWater")
private Water water;
}
// 简写技巧:当变量名与Bean名一致时,连name属性都不用写
@Resource
private Water hotWater; // 自动匹配名字为hotWater的Bean
特殊情况:名字找不到,会自动降级按类型找
如果指定的名字找不到,@Resource不会直接报错,会自动降级,按类型查找匹配的Bean:
@Component
public class Cup {
// 第一步:找名字=abc的Bean → 找不到
// 第二步:自动降级,找Water类型的Bean → 找到后注入
@Resource(name = "abc")
private Water water;
}
可视化总结
@Resource 查找流程:
【找名字】→ 找到 → 直接注入
【找名字】→ 找不到 → 自动降级,按类型匹配
【找名字】+ 按类型 → 都找不到 → 报错
四、终极对比表(一眼看懂核心差异)
| 特性 | @Autowired | @Resource |
|---|---|---|
| 归属 | Spring 框架专属 | Java 官方标准(跨框架通用) |
| 默认匹配规则 | 按类型(byType) | 按名字(byName) |
| 多实现类时 | 必须加 @Qualifier 指定名字,否则报错 | 直接用 name 属性 / 变量名匹配,无需额外注解 |
| 匹配失败处理 | 找不到对应类型 → 直接报错 | 找不到对应名字 → 自动降级按类型匹配 |
| 使用场景 | 纯Spring项目,无需精准指定Bean名字 | 需精准指定Bean、跨框架开发,追求稳健性 |
五、最简单的使用口诀(记牢不踩坑)
- 只有一个实现类:两个注解随便用,效果完全一致,怎么方便怎么来;
- 有多个实现类,想精准指定:优先用 @Resource,无需额外注解,简洁高效;
- 纯Spring项目,需配合
@Qualifier灵活匹配:用 @Autowired 更贴合Spring生态。
总结
- @Autowired = 先看类型,多实现类必报错,需搭配
@Qualifier“指名道姓”; - @Resource = 先看名字,精准匹配更灵活,名字找不到自动降级按类型匹配;
- 日常开发:优先用 @Resource,指定Bean名字更直观,能有效减少报错,提升开发效率。