@Autowired和@Resource的区别
一、本质
@Autowired 和 @Resource 的「注入匹配规则不同」
@Autowired优先按「类型」注入,IDE 静态检查时没识别到「AdminDao类型」的 Bean,所以报红;@Resource优先按「名称」注入,直接找 Spring 容器中「名称为adminDao」的 Bean(MyBatis 生成的 Mapper Bean 名称默认是「接口名首字母小写」,刚好匹配),IDE 能明确识别到,所以不报错。
二、核心区别
| 对比维度 | @Autowired(Spring 注解) | @Resource(JDK 原生注解,JSR-250 规范) |
|---|---|---|
| 依赖来源 | Spring 框架提供,耦合 Spring | JDK 自带,无框架耦合,兼容性更强 |
| 注入核心依据 | 优先按「类型(Type)」匹配,其次按「名称(Name)」 | 优先按「名称(Name)」匹配,其次按「类型(Type)」 |
| 支持的匹配属性 | 需配合 @Qualifier 注解指定名称(如 @Qualifier("adminDao")) | 可直接通过 name 属性指定名称(如 @Resource(name="adminDao")) |
| 是否支持依赖 required | 有 required 属性(默认 true,找不到 Bean 会报错) | 无 required 属性(找不到 Bean 直接报错,需手动处理) |
| 匹配灵活性 | 类型匹配优先,适合同一类型多个 Bean 时用 @Qualifier 区分 | 名称匹配优先,适合明确知道 Bean 名称的场景 |
| IDE 静态识别友好度 | 对动态代理 Bean(如 MyBatis Mapper)的类型识别较弱,易报红 | 对 Bean 名称的识别更直接,不易误报 |
三、案例
@Service
public class AdminServiceImpl implements AdminService {@Autowiredprivate AdminDao adminDao;
}
@Mapper
public interface AdminDao {Admin login(Admin admin);}在service中注入AdminDao ,使用@Autowired注解,会有提示,而使用@Resource不会出现提示。
AdminDao 是 MyBatis 的 Mapper 接口,Spring 容器中实际存在的 Bean 是:
Bean 名称:默认是 adminDao(MyBatis 自动将接口名首字母小写作为 Bean 名称);
Bean 类型:不是 AdminDao 接口本身,而是 MyBatis 动态生成的「代理类」(比如 AdminDao$Proxy@xxx)
这时候两者的注入逻辑差异就体现了:
@Resource 注入逻辑(生效原因)
@Resource默认先找「名称为adminDao」的 Bean;- Spring 容器中刚好有一个名称为
adminDao的代理 Bean(MyBatis 生成的),直接匹配成功; - IDE 能明确识别到「容器中有名称为
adminDao的 Bean」,所以不报错。
@Autowired 报红原因(分两种情况)
情况 1:IDE 静态检查误报(最可能)
@Autowired优先按「类型」匹配,IDE 在静态检查时,只会找「类型为AdminDao的 Bean」;- 但容器中实际的 Bean 类型是「MyBatis 动态代理类」,IDE 无法提前识别这个代理类和
AdminDao接口的关联,所以静态检查时认为「没有AdminDao类型的 Bean」,从而报红; - 但 运行时可能不报错(因为 Spring 运行时会通过「类型兼容」识别到代理类实现了
AdminDao接口,最终能注入成功)。
情况 2:确实没匹配到类型(少部分情况)
- 若你的项目中
@MapperScan配置有误,或 MyBatis 依赖有问题,导致代理 Bean 未被正确注册为「AdminDao类型的 Bean」; @Autowired按类型找不到匹配的 Bean,不仅 IDE 报红,运行时还会抛出No qualifying bean of type 'com.qcby.dao.AdminDao' available错误。
四、如果想继续用 @Autowired,怎么解决报红?
方案 1:配合 @Qualifier 指定 Bean 名称
用 @Qualifier 明确告诉 @Autowired 按名称匹配,绕开类型识别问题:
@Autowired和@Qualifier注解一起使用
@Service
public class AdminServiceImpl implements AdminService {// 核心:@Qualifier 指定 Bean 名称为 adminDao@Autowired@Qualifier("adminDao") private AdminDao adminDao;// 其他代码不变...
}方案 2:给 Mapper 接口加 @Repository 注解(辅助 IDE 识别)
在 AdminDao 接口上再加一个 @Repository 注解,帮助 IDE 识别这是一个 Spring 管理的 Bean,减少静态检查误报:
@Mapper
@Repository // 加上这个注解,IDE 能更清晰识别这是一个 Bean
public interface AdminDao {Admin login(Admin admin);
}之后刷新maven依赖和idea的缓存。
五、总结
@Autowired 和 @Resource 的核心区别:
两者均为Spring项目中依赖注入的核心注解,核心差异集中在【依赖来源、注入逻辑、功能特性及兼容性】四大维度:
@Autowired是Spring框架提供的注解,耦合Spring生态,注入时优先按照类型匹配,若同一类型存在多个bean,需搭配@Qualifier注解指定bean名称,且支持required属性控制依赖是否必须存在(默认为true);
@Resource是JDK原生注解,无框架耦合,兼容性更强,注入时优先按照名称匹配(默认取字段名作为bean名称),其次才按类型匹配,无需额外注入即可指定名称(通过name属性),但不支持required配置。
此外,在实际场景中,@Autowired对MyBatis动态代理Mapper等特殊Bean的静态识别较弱,易出现IDE误报,而@Resource因名称匹配的直接性,对这类场景的兼容性更优。使用上,@Autowired更适合Spring专属项目中需类型匹配的场景,@Resource更适合追求低耦合、明确Bean名称的跨框架兼容场景。
