❗️❗️❗️
看了一下大部分的文章都只讲了区别是byType和byName,具体什么是byType和byName却没有详尽的解释,文章末尾会具体的讲清楚这些区别。
目录
@Autowired 和 @Resource
一、@Autowired
二、@Resource
三、byType(按类型注入)
四、byName(按名称注入)
五、byName和byType放一起对比
六、表格对比
七、一句话总结
八、开发使用建议
@Autowired 和 @Resource
两者都是依赖注入注解,用来把 Spring 容器中的 Bean 注入到变量上,核心区别:
@Autowired是Spring 框架自带注解;
@Resource是Java 官方标准注解。
一、@Autowired
@Autowired private UserService userService;- 所属包:
org.springframework.beans.factory.annotation.Autowired,Spring 特有。 - 默认注入规则:按类型(byType)
- Spring 去容器里找类型完全匹配的 Bean 注入。
- 如果同类型有多个 Bean,会报错
NoUniqueBeanDefinitionException。- 解决:搭配
@Qualifier("beanName")指定 bean 名称。
@Autowired @Qualifier("userServiceImpl1") private UserService userService; - 解决:搭配
- 默认要求 Bean 必须存在,找不到就抛异常; 可以设置
required = false变成非必须:@Autowired(required = false) - 支持位置:成员变量、setter 方法、构造方法
Spring4.3+,构造方法上的
@Autowired可以省略,只有一个构造器时自动注入。
二、@Resource
@Resource private UserService userService;- 所属包:
javax.annotation.Resource(jdk8)/jakarta.annotation.Resource(jdk9+),Java 规范,不是 Spring 专属。 - 注入顺序:先按名称 (byName),找不到再按类型 (byType)
- 优先:拿变量名当作 bean 名字去容器查找;
- 按名字找不到,退化成按类型 byType 注入。
- 可以手动指定名字:
@Resource(name = "userServiceImpl1")
- 没有 required 属性,找不到 Bean 直接报错。
- 支持位置:成员变量、setter 方法,不支持构造方法注入。
三、byType(按类型注入)
@Autowired默认 byType:根据变量的类型,去 Spring 容器里找这个类型的 Bean 对象,找到就赋值给变量。❗️❗️❗️重点:看变量的类型,不是看变量名字。
例子
1. 接口 + 实现类
// 接口 public interface UserService { //.... } // 实现类1,交给Spring管理 @Service public class UserServiceImpl implements UserService { //.... }Controller 里注入:
// 变量类型:UserService @Autowired private UserService userService;✅ byType 执行过程:
- 看变量
userService的类型:UserService - Spring 去容器查找:有没有 Bean 是 UserService 类型(或者它的实现类)
- 找到
UserServiceImpl这个 Bean,注入进来。
变量名字叫
aaa也完全没问题!因为 byType不看名字
@Autowired private UserService aaa; // 照样正常注入,只看类型UserService2. 同一个类型,容器里面有多个 Bean
通俗讲,如果这个接口有多个实现类:
@Service public class UserServiceImpl2 implements UserService { //.... }现在容器里有两个 UserService 类型的 Bean:UserServiceImpl、UserServiceImpl2
@Autowired private UserService userService; //👉 Spring:找到了 2 个同类型 Bean,不知道注入哪一个! //这时候就会直接抛异常: // NoUniqueBeanDefinitionException 不唯一 Bean 异常。解决办法:搭配 @Qualifier 指定 Bean 名称
@Autowired @Qualifier("userServiceImpl") // 指定bean名字 private UserService userService;
@Qualifier是按 Bean 名称筛选,和 byType 配合使用。先用 byType 找到所有同类型 Bean,再根据名字从中挑选一个。
四、byName(按名称注入)
byName:根据「Bean 的名字 (beanName)」进行匹配注入。
@Resource优先规则:拿【变量名】当作 beanName,去容器查找 bean。
@Resource private UserService abc;👉 变量名是abc→@Resource第一步:去容器找 beanName = "abc"的 Bean。
1、Bean 默认名字规则(@Service/@Component)
当你写:
@Service public class UserServiceImpl implements UserService{ }Spring 默认生成 beanName:类名首字母小写→userServiceImpl✅
这个 Bean 在容器里名字:userServiceImpl,类型:UserServiceImpl(实现了 UserService)
此时容器里:beanName=
userServiceImpl,类型 =UserServiceImpl
示例
@Resource private UserService abc;- 第一步:
@Resource拿变量名abc,去容器搜索beanName="abc" - 容器里没有叫 abc 的 Bean!(只有
userServiceImpl) - byName 查找失败 →降级 byType
- 按类型
UserService去容器找 Bean,找到userServiceImpl注入成功。
👉 所以这个代码不会报错,可以正常运行,只是 byName 没命中,走了 byType 兜底。
2、那什么时候 byName 能命中?两种方式
方式 1:让 Bean 的名字和变量名一致
@Service("abc") // 手动指定beanName为abc public class UserServiceImpl implements UserService{ }@Resource private UserService abc; //变量名abc@Resource拿变量名abc,去容器找 beanName=abc- ✅ 找到了!直接注入,不走 byType。
方式 2:变量名等于默认 beanName
@Service public class UserServiceImpl implements UserService{ } // beanName默认:userServiceImpl@Resource private UserService userServiceImpl; //变量名=userServiceImpl变量名和 beanName 一致,byName 直接命中。
三、手动指定 name 属性,跳过变量名
@Resource(name="xxx")会忽略变量名,直接用你写的名字去查找:
// 直接指定去找beanName="userServiceImpl",不管变量名叫什么 @Resource(name = "userServiceImpl") private UserService abc;哪怕变量名叫 abc,这里也不会拿 abc 去匹配,优先用 name 属性的值。
五、byName和byType放一起对比
// 场景:容器中只有一个Bean:beanName=userServiceImpl,类型UserService // @Autowired:只看类型UserService,变量名随便写abc,完全不影响 @Autowired private UserService abc; // @Resource:先拿变量名abc找beanName=abc,找不到,再按类型UserService查找 @Resource private UserService abc;六、表格对比
| 特性 | @Autowired | @Resource |
|---|---|---|
| 来源 | Spring 框架注解 | JSR-250 Java 标准注解 |
| 默认注入方式 | byType(按类型) | byName(按名称)→找不到再 byType |
| 多 Bean 处理 | 需要配合 @Qualifier 指定名字 | 优先变量名,也可 name 属性指定 |
| required 属性 | ✅ 支持 @Autowired (required=false) | ❌ 无 |
| 构造方法注入 | ✅ 支持 | ❌ 不支持 |
| 框架耦合 | 强耦合 Spring | 标准注解,切换容器(如 JBoss)不用改代码 |
七、一句话总结
@Autowired:Spring 提供,默认按类型注入,多实例搭配@Qualifier,支持构造注入。@Resource:Java 标准,先按名字,名字找不到再按类型,不能用于构造器注入。
八、开发使用建议
- SpringBoot 项目,绝大多数场景推荐
@Autowired(构造注入最佳实践) - 如果想降低框架耦合,或者想直接按变量名匹配 bean,可以用
@Resource。