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