Skip to main content

@Autowired和@Resource有何区别?

作者:程序员马丁

在线博客:https://open8gu.com

note

大话面试,技术同学面试必备的八股文小册,以精彩回答应对深度问题,助力你在面试中拿个offer。

回答话术

@Autowired@Resource 都是在 Spring 里比较常用的依赖注入注解,两者都支持属性注入、构造器注入和 Setter 方法注入三种主要的注入模式,也都支持 Spring 的组合注解机制。

1. 来源不同

@Autowired 是 Spring 提供的注解,位于 org.springframework.beans.factory.annotation 包。

@Resource 则是 JSR250 规范注解, 是 JDK 自带的。在 JDK9 之前,它位于 javax.annotation 包,在 JDK9 及之后,它位于 jakarta.annotation

2. 拥有的属性不同

@Autowired注解只有一个 require 属性用于指定依赖性非必填,因此当仅通过类型无法确认唯一的依赖对象时,必须通过 @Qualifier注解配合指定 beanName。而 @Resource注解自带 nametype 两个属性,这决定了 @Resource 可以更精确的指定要注入的 Bean。

@Component("a")
public class A implements Letter {}
@Component("b")
public class B implements Letter {}

@Component
public class Example {

@Qualifier("a")
@Autowire
private Letter letterA;

@Resource(type = B.class, name = "b") // 等价于 @Autowire + @Qualifier
private Letter letterB;
}

不过,@Resource 相较于 @Autowired 没有 require 属性,因此它默认就是非必填的,当然,它也和 @Autowired 一样,允许通过加 @Nullable 注解,或将注入类型改为 Optional 实现:

@Component("a")
public class A implements Letter {}
@Component("b")
public class B implements Letter {}

@Component
public class Example {

// 下述四种写法效果一致,最终都是 null 或 empty

@Qualifier("c")
@Autowire(require = false)
private Letter letterC;

@Resource(name = "d")
private Letter letterD;

@Qualifier("e")
@Autowire
private Letter letterE;

@Qualifier("f")
@Autowire
private Optional<Letter> letterF;
}

3. 默认的匹配方式不同

两个注解一个广为人知的区别是,@Autowired 默认是按类型匹配的,而 @Resource 则是默认按名称匹配的:

@Component
public class Example {

@Autowire // 优先寻找类型为 Letter 的 Bean
private Letter letterA;

@Resource // 优先寻找 beanName 为 “letterB” 的 Bean
private Letter letterB;
}

这种说法没有问题,但是只是“默认”,实际上两者都支持多维度匹配,即先按名称/类型匹配,没有的话再回退到按类型/名称匹配

比如:

@Component("a")
public class A implements Letter {}
@Component("b")
public class B implements Letter {}

@Component
public class Example {

// 先寻找类型为 Letter 的 Bean
// 再从类型为 Letter 的 Bean 中寻找名称为 'a' 的 Bean
@Autowire
private Letter a;

// 先寻找名称为 letterB 的 Bean
// 如果找不到,再寻找类型为 B 的 Bean
@Resource
private B letterB;
}

因此,更严格一点说,两者的匹配方式不同:

  • @Autowired 先尝试按类型匹配,如果有多个结果,则再按名称匹配
  • @Resource 先尝试按名称匹配,没有结果则再按类型匹配

Spring 称这种“先 xx,不行在 xx”的机制为回退(fallback)。

4. 注解处理器不同

这一点严格来说应该叫做用于“处理注解的后处理器不同”。

@Autowired 注解通过 AutowiredAnnotationBeanPostProcessor 这个后处理器处理的,而 @Resource 注解则是通过 CommonAnnotationBeanPostProcessor 这个后处理器处理的。不过两者在底层都会被解析为 InjectionMetadata,并最终完成注入。