Spring 依赖注入:@Autowired 与@Resource 深度解析
在 Spring 生态里,依赖注入是核心机制之一。除了 Spring 自家的 @Autowired,我们还能用到 JSR-250 规范定义的注解,比如 @Resource、@PostConstruct 以及 @PreDestroy。
很多人容易混淆这两个注入注解,其实它们的作用类似,但底层策略不同:@Autowired 默认按类型(byType)自动注入,而 @Resource 默认按名称(byName)自动注入。
@Resource 的装配逻辑
@Resource 有两个关键属性:name 和 type。
- name:解析为 Bean 的名字。
- type:解析为 Bean 的类型。
Spring 容器处理 @Resource 时的装配顺序如下:
- 如果同时指定了
name和type,则从上下文中找到唯一匹配的 Bean 进行装配,找不到会抛异常。 - 如果只指定了
name,则查找名称(id)匹配的 Bean,找不到抛异常。 - 如果只指定了
type,则查找类型匹配的唯一 Bean。如果找不到或找到多个,都会抛异常。 - 如果既没指定
name也没指定type,默认按 byName 方式装配;如果没有匹配,则回退为原始类型匹配。
两者对比与实战建议
1. 使用位置灵活
两者都可以写在字段上,也可以写在 Setter 方法上。不过在实际开发中,为了代码简洁,我更推荐直接在字段上使用。
2. 注入策略差异
@Autowired 属于 Spring 体系,默认必须要求依赖对象存在。如果允许 null 值,可以设置 required=false。若需结合名称装配,通常配合 @Qualifier 使用:
@Autowired
@Qualifier("baseDao")
private BaseDao baseDao;
@Resource 属于 J2EE 标准,默认按名称装配。如果注解写在字段上,默认取字段名作为名称查找;写在 Setter 方法上,默认取属性名。只有当找不到名称匹配的 Bean 时,才会按照类型进行装配。一旦指定了 name 属性,就只会按名称装配:
@Resource(name = "baseDao")
private BaseDao baseDao;
3. 耦合度考量
推荐使用 @Resource 注解在字段上,这样就不用写 setter 方法了,并且这个注解是属于 J2EE 标准的,减少了与 Spring 框架的强耦合。这样代码看起来更优雅,也更容易迁移到其他支持 JSR-250 的环境中。
总的来说,如果你希望减少对外部框架的依赖,或者对 Bean 的名称有明确控制,@Resource 是个不错的选择;如果完全信任 Spring 容器且主要关注类型匹配,@Autowired 同样高效。

