Spring 注解揭秘:@Autowired 和 @Resource 的用法详解与避坑建议
文章目录
- 1. 什么是依赖注入?
- 2. @Autowired 是什么?
- @Autowired 的工作原理:
- 常见坑及解决方法:
- 3. @Resource 是什么?
- @Resource 的工作原理:
- 常见坑及解决方法:
- 4. @Autowired 与 @Resource 的区别
- 5. 如何选择 @Autowired 和 @Resource?
- 6. 常见避坑指南
- 总结
- 推荐阅读文章
在 Spring 框架中,依赖注入(Dependency Injection,简称 DI)是一个核心概念,而
@Autowired
和
@Resource
是实现依赖注入的两种常用注解。通过简单明了的例子,我将详细解释这两者的用法、背后的原理,并给出一些常见的坑和解决方法。
1. 什么是依赖注入?
依赖注入就是把一个对象需要的依赖对象自动赋予给它,而不是手动创建或查找。想象一下,一个对象需要一个“工具”,而你无需自己去创建这个工具,只要告诉 Spring,它就会帮你把这个工具注入进来。依赖注入帮助开发者避免写重复的代码,也提高了程序的可测试性。
2. @Autowired 是什么?
@Autowired
是 Spring 的核心注解之一,用于自动将一个 bean 注入到另一个 bean 中。简单来说,它帮助我们完成类与类之间的依赖关系。
@Service
public class MyService {@Autowiredprivate MyRepository myRepository;public void doSomething() {myRepository.save();}
}
上面代码中的 @Autowired
表示 MyService
类需要一个 MyRepository
类型的依赖,Spring 会自动找到对应的 bean 并注入。
@Autowired 的工作原理:
- 默认按类型注入:
@Autowired
默认是按类型(byType)注入的,Spring 会根据类型查找合适的 bean 并注入。 - 可选的按名称注入:如果存在多个同类型的 bean,Spring 可能会模棱两可。这时,可以用
@Qualifier
注解进一步通过名称指定。 - 构造函数、字段、方法注入:
@Autowired
可以用在构造函数、字段、甚至 setter 方法上。
常见坑及解决方法:
-
多个同类型的 bean:当有多个同类型的 bean 时,Spring 不知道该注入哪个。这时可以用
@Qualifier
注解来明确指定要注入的 bean。@Autowired @Qualifier("specificBean") private MyRepository myRepository;
-
null 值注入:如果没有匹配的 bean,可能会导致
NullPointerException
。可以用required = false
让注入变为可选。@Autowired(required = false) private MyRepository myRepository;
3. @Resource 是什么?
@Resource
是来自 JSR-250 标准(Java 规范请求)的注解,Spring 也支持它。与 @Autowired
类似,它也用于依赖注入,但其工作方式稍有不同。
@Service
public class MyService {@Resourceprivate MyRepository myRepository;public void doSomething() {myRepository.save();}
}
@Resource 的工作原理:
- 默认按名称注入:
@Resource
默认是按名称(byName)注入的,即 Spring 会寻找与属性名匹配的 bean 名称。如果找不到相应的名称,再按类型查找。 - 仅支持字段或 setter 方法注入:与
@Autowired
不同,@Resource
不能用于构造函数注入。
常见坑及解决方法:
-
名称冲突:如果 bean 名称与字段名不匹配,
@Resource
无法按名称找到 bean。这时可以显式指定名称。@Resource(name = "myRepositoryBean") private MyRepository myRepository;
-
类型不匹配问题:
@Resource
是按名称优先查找的,但如果没有匹配的名称,才会按类型查找。因此,如果名称和类型都不匹配,可能会报错。
4. @Autowired 与 @Resource 的区别
特性 | @Autowired | @Resource |
---|---|---|
注入方式 | 默认按类型注入(byType) | 默认按名称注入(byName) |
注解来源 | Spring 专用 | JSR-250 标准 |
构造函数注入 | 支持 | 不支持 |
可选注入 | required = false | 不直接支持 |
多个同类型 bean 处理 | 需要 @Qualifier | 通过 @Resource(name = ...) |
5. 如何选择 @Autowired 和 @Resource?
- 首选
@Autowired
:如果你正在开发一个纯 Spring 项目,建议首选@Autowired
,因为它是 Spring 的原生注解,功能强大且灵活,尤其适合复杂的依赖注入场景。 - 跨框架使用
@Resource
:如果你正在使用 J2EE 规范或者需要与其他 Java EE 组件兼容,@Resource
是更好的选择,因为它是 JSR-250 标准的一部分,能确保兼容性。
6. 常见避坑指南
- 避免类型冲突:如果有多个相同类型的 bean,务必使用
@Qualifier
或@Resource(name)
明确指定。 - 依赖可选注入:如果某个依赖可能不存在,使用
@Autowired(required = false)
来避免运行时错误。 - 构造函数优先:对于强制性依赖,建议使用构造函数注入(
@Autowired
),这种方式能确保对象在初始化时完全就绪,不会遗漏依赖。
总结
@Autowired
是 Spring 的专有注解,按类型注入,支持构造函数、字段、方法注入,功能强大且灵活。@Resource
来自 JSR-250 标准,按名称注入,通常用于跨框架兼容场景。- 在实际开发中,优先选择
@Autowired
,除非需要与 Java EE 规范兼容。通过明确注入类型、使用合适的注解方式,可以避免许多常见的坑。
推荐阅读文章
1、使用 Spring 框架构建 MVC 应用程序:初学者教程
2、有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
3、如何理解应用 Java 多线程与并发编程?
4、Java Spring 中常用的 @PostConstruct 注解使用总结
5、线程 vs 虚拟线程:深入理解及区别
6、深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
7、10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
8、“打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
9、Java 中消除 If-else 技巧总结
10、线程池的核心参数配置(仅供参考)
11、【人工智能】聊聊Transformer,深度学习的一股清流(13)
12、Java 枚举的几个常用技巧,你可以试着用用