@@ -232,37 +232,40 @@ Spring 内置的 `@Autowired` 以及 JDK 内置的 `@Resource` 和 `@Inject` 都
232232
233233### @Autowired 和 @Resource 的区别是什么?
234234
235- ` Autowired ` 属于 Spring 内置的注解,默认的注入方式为 ` byType ` (根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类) 。
235+ ` @ Autowired` 是 Spring 内置的注解,默认注入逻辑为 ** 先按类型(byType)匹配,若存在多个同类型 Bean,则再尝试按名称(byName)筛选 ** 。
236236
237- ** 这会有什么问题呢? ** 当一个接口存在多个实现类的话, ` byType ` 这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。
237+ 具体来说:
238238
239- 这种情况下,注入方式会变为 ` byName ` (根据名称进行匹配),这个名称通常就是类名(首字母小写)。就比如说下面代码中的 ` smsService ` 就是我这里所说的名称,这样应该比较好理解了吧。
239+ 1 . 优先根据接口 / 类的类型在 Spring 容器中查找匹配的 Bean。若只找到一个符合类型的 Bean,直接注入,无需考虑名称;
240+ 2 . 若找到多个同类型的 Bean(例如一个接口有多个实现类),则会尝试通过** 属性名或参数名** 与 Bean 的名称进行匹配(默认 Bean 名称为类名首字母小写,除非通过 ` @Bean(name = "...") ` 或 ` @Component("...") ` 显式指定)。
240241
241- ``` java
242- // smsService 就是我们上面所说的名称
243- @Autowired
244- private SmsService smsService;
245- ```
242+ 当一个接口存在多个实现类时:
243+
244+ - 若属性名与某个 Bean 的名称一致,则注入该 Bean;
245+ - 若属性名与所有 Bean 名称都不匹配,会抛出 ` NoUniqueBeanDefinitionException ` ,此时需要通过 ` @Qualifier ` 显式指定要注入的 Bean 名称。
246246
247- 举个例子, ` SmsService ` 接口有两个实现类: ` SmsServiceImpl1 ` 和 ` SmsServiceImpl2 ` ,且它们都已经被 Spring 容器所管理。
247+ 举例说明:
248248
249249``` java
250- // 报错,byName 和 byType 都无法匹配到 bean
250+ // SmsService 接口有两个实现类:SmsServiceImpl1、SmsServiceImpl2(均被 Spring 管理)
251+
252+ // 报错:byType 匹配到多个 Bean,且属性名 "smsService" 与两个实现类的默认名称(smsServiceImpl1、smsServiceImpl2)都不匹配
251253@Autowired
252254private SmsService smsService;
253- // 正确注入 SmsServiceImpl1 对象对应的 bean
255+
256+ // 正确:属性名 "smsServiceImpl1" 与实现类 SmsServiceImpl1 的默认名称匹配
254257@Autowired
255258private SmsService smsServiceImpl1;
256- // 正确注入 SmsServiceImpl1 对象对应的 bean
257- // smsServiceImpl1 就是我们上面所说的名称
259+
260+ // 正确:通过 @Qualifier 显式指定 Bean 名称 "smsServiceImpl1"
258261@Autowired
259262@Qualifier (value = " smsServiceImpl1" )
260263private SmsService smsService;
261264```
262265
263- 我们还是建议通过 ` @Qualifier ` 注解来显式指定名称而不是依赖变量的名称。
266+ 实际开发实践中, 我们还是建议通过 ` @Qualifier ` 注解来显式指定名称而不是依赖变量的名称。
264267
265- ` @Resource ` 属于 JDK 提供的注解,默认注入方式为 ` byName ` 。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为 ` byType ` 。
268+ ` @Resource ` 属于 JDK 提供的注解,默认注入逻辑为 ** 先按名称( byName)匹配,若存在多个同类型 Bean,则再尝试按类型( byType)筛选 ** 。
266269
267270` @Resource ` 有两个比较重要且日常开发常用的属性:` name ` (名称)、` type ` (类型)。
268271
@@ -287,13 +290,15 @@ private SmsService smsServiceImpl1;
287290private SmsService smsService;
288291```
289292
290- 简单总结一下:
293+ ** 简单总结一下** :
291294
292295- ` @Autowired ` 是 Spring 提供的注解,` @Resource ` 是 JDK 提供的注解。
293296- ` Autowired ` 默认的注入方式为` byType ` (根据类型进行匹配),` @Resource ` 默认注入方式为 ` byName ` (根据名称进行匹配)。
294297- 当一个接口存在多个实现类的情况下,` @Autowired ` 和` @Resource ` 都需要通过名称才能正确匹配到对应的 Bean。` Autowired ` 可以通过 ` @Qualifier ` 注解来显式指定名称,` @Resource ` 可以通过 ` name ` 属性来显式指定名称。
295298- ` @Autowired ` 支持在构造函数、方法、字段和参数上使用。` @Resource ` 主要用于字段和方法上的注入,不支持在构造函数或参数上使用。
296299
300+ 考虑到 ` @Resource ` 的语义更清晰(名称优先),并且是 Java 标准,能减少对 Spring 框架的强耦合,我们通常** 更推荐使用 ` @Resource ` ** ,尤其是在需要按名称注入的场景下。而 ` @Autowired ` 配合构造器注入,在实现依赖注入的不可变性和强制性方面有优势,也是一种非常好的实践。
301+
297302### 注入 Bean 的方式有哪些?
298303
299304依赖注入 (Dependency Injection, DI) 的常见方式:
0 commit comments