简介:在SpringBoot开发中,@Autowired与@Resource是最常用的两个依赖注入注解,但很多开发者对二者的装配策略、来源规范及适用场景并不清晰。本文从装配方式、匹配优先级、注解来源、字段名回退机制等维度系统对比,帮助你彻底厘清差异,写出更健壮的注入代码。
在日常的SpringBoot项目开发中,依赖注入几乎是每个开发者每天都要面对的环节。而在众多注入方式里,@Autowired和@Resource这两个注解的出现频率最高。很多同学在写代码时随手用一个,感觉都能跑通,也就没有深究。但一旦遇到“同类型Bean存在多个”或者“需要按名称精确注入”的场景,两者的行为差异就会立刻暴露出来,甚至导致启动失败或者注入错对象。本文将从底层机制出发,系统地梳理这两个注解的核心区别,并给出实践中的选型建议。
这是最根本的区别,也是理解后续所有行为差异的基础。
@Autowired是Spring框架自身提供的注解,位于org.springframework.beans.factory.annotation包下。它完全由Spring容器负责解析和处理,是Spring生态中特有的注入方式。
@Resource则不同,它来自Java标准规范(JSR-250),位于jakarta.annotation(早期为javax.annotation)包下。也就是说,它是Java平台层面的通用注解,理论上不依赖Spring也能被其他容器识别。Spring在实现时对它有完整的支持,因此我们在SpringBoot项目中同样可以使用。
一句话总结:@Autowired是Spring的“亲儿子”,@Resource是Java标准的“通用规范”,Spring只是把它接了过来。
这是两者最常被拿来对比的一点。
@Autowired默认采用byType策略。也就是说,Spring会根据字段或参数的类型去容器中查找匹配的Bean。如果容器中该类型的Bean只有一个,直接注入成功。
@Servicepublic class OrderService {@Autowiredprivate UserService userService;}
在UserService类型只有一个实例时,上面的代码可以稳定工作。
此外,@Autowired有一个required属性,默认值为true,表示必须找到匹配的Bean,否则启动报错。如果业务上允许某个依赖缺失,可以显式设置:
@Autowired(required = false)private UserService userService;
这样即使容器中没有UserService,项目也能正常启动,字段为null。
@Resource的默认策略与@Autowired相反,它优先按名称匹配。具体逻辑是:
name属性,则严格按该名称查找Bean;name,则默认使用字段名或setter方法名作为Bean名称去查找;
@Servicepublic class OrderService {@Resourceprivate UserService userService;}
这段代码中,@Resource会先尝试查找名为userService的Bean。如果存在,则注入;如果不存在,再按UserService类型去匹配。
这是区分两者最关键、也最容易踩坑的场景。
假设容器中存在两个UserService类型的Bean:
@Service("userServiceA")public class UserServiceA implements UserService { }@Service("userServiceB")public class UserServiceB implements UserService { }
此时再使用@Autowired按类型注入:
@Autowiredprivate UserService userService;
Spring会因为无法确定使用哪个Bean而抛出NoUniqueBeanDefinitionException,项目启动失败。解决办法通常是配合@Qualifier指定名称:
@Autowired@Qualifier("userServiceA")private UserService userService;
或者将字段名改为userServiceA,让Spring按字段名匹配(这属于隐性回退,不推荐依赖)。
而@Resource在这种情况下处理起来更自然:
@Resource(name = "userServiceA")private UserService userService;
或者直接利用字段名:
@Resourceprivate UserService userServiceA;
由于@Resource优先按名称匹配,只要名称对得上,就不会出现“多个候选”的歧义问题。
| 维度 | @Autowired | @Resource |
|---|---|---|
| 来源 | Spring框架 | Java标准(JSR-250) |
| 默认策略 | 按类型(byType) | 按名称(byName) |
| 名称匹配 | 需配合@Qualifier | 默认使用字段名/name属性 |
| 类型回退 | 无(类型是首选) | 名称找不到时回退到类型 |
| required属性 | 支持(默认true) | 不支持,找不到直接报错 |
| 适用位置 | 字段、构造器、setter、参数 | 字段、setter方法 |
@Resource写起来更简洁,不用额外加@Qualifier。@Autowired,因为@Resource不支持构造器和参数级别。@Autowired(required = false)是唯一的选项。@Autowired和@Resource的核心差异可以归纳为一句话:前者默认按类型装配,是Spring的原生注解;后者默认按名称装配,是Java标准注解,并在名称匹配失败时回退到类型匹配。理解这一点,就能在遇到多实现、多候选、需要精确注入等场景时快速做出正确选择,避免启动报错或注入错误对象。实际开发中,建议结合项目规范和具体场景灵活使用,而不是机械地认为某一个“更好”。