招商银行面试题:深入解析 Spring 框架中的 @Autowired 和 @Resource 注解的区别与应用场景

今天我们将探讨在 Spring 框架中,@Autowired@Resource 注解之间的差异及其应用场景。了解这些注解的使用能够帮助开发者更好地进行 Bean 的注入,提高代码的可读性和可维护性。

@Autowired@Resource 的基本区别

Spring框架内置的 @Autowired 注解以及 JDK 提供的 @Resource@Inject 注解都可以用于注入 Bean。以下是它们的基本信息:

AnnotationPackageSource
@Autowiredorg.springframework.bean.factorySpring 2.5+
@Resourcejavax.annotationJava JSR-250
@Injectjavax.injectJava JSR-330

在实际开发中,@Autowired@Resource 是使用频率较高的注解。

@Autowired 的工作原理

@Autowired 注解是 Spring 提供的,其默认的注入方式为 byType,即通过类型进行依赖匹配。这意味着 Spring 将优先根据接口类型定位并注入相应的 Bean(接口的实现类)。

注入冲突的处理

当一个接口有多个实现类时,使用 byType 注入将导致无法确定注入哪个具体的实现类。在这种情况下,Spring 会尝试使用 byName 的方式进行匹配,通常名称是类名的小写形式。例如,以下代码中的 smsService 就是类的名称:

// smsService 是我们上面所提到的名称  
@Autowired  
private SmsService smsService;  

如果 SmsService 接口有两个实现类 SmsServiceImpl1SmsServiceImpl2,且它们都被 Spring 管理,则可能会出现如下情况:

// 报错,byName 和 byType 都无法匹配到 bean  
@Autowired  
private SmsService smsService;  
// 正确注入 SmsServiceImpl1 对应的 bean  
@Autowired  
private SmsService smsServiceImpl1;  
// 正确注入 SmsServiceImpl1 对应的 bean  
@Autowired  
@Qualifier(value = "smsServiceImpl1")  
private SmsService smsService;  

建议使用 @Qualifier 注解显式指定名称,而不是依赖于变量名称。

@Resource 的工作原理

@Resource 是 JDK 提供的注解,其默认的注入方式为 byName。如果通过名称找不到相应的实现类,则会转为 byType 进行匹配。@Resource 提供了两个非常重要且常用的属性:name(名称)和 type(类型)。

public @interface Resource {  
    String name() default "";  
    Class<?> type() default Object.class;  
}  

使用 @Resource 时,如果仅设置 name 属性,则注入方式为 byName;如果仅设置 type 属性,则为 byType;如果同时设置 nametype 属性(不推荐),则采用 byType + byName 的方式。

// 报错,byName 和 byType 都无法匹配到 bean  
@Resource  
private SmsService smsService;  
// 正确注入 SmsServiceImpl1 对应的 bean  
@Resource  
private SmsService smsServiceImpl1;  
// 正确注入 SmsServiceImpl1 对应的 bean(推荐使用这种方式)  
@Resource(name = "smsServiceImpl1")  
private SmsService smsService;  

总结

  • @Autowired 是由 Spring 提供的注解,而 @Resource 是 JDK 提供的注解。
  • @Autowired 默认采用 byType 的注入方式,而 @Resource 则默认采用 byName
  • 当一个接口有多个实现类时,@Autowired@Resource 都需要通过名称来确保正确匹配到对应的 Bean。可以通过 @Qualifier 来显式指定名称,而 @Resource 则可以通过 name 属性来达成。

通过对 @Autowired@Resource 的理解,开发者能够在项目中更高效地进行依赖注入,避免潜在的错误与混淆。