@Autowired和@Resource有何区别?
作者:程序员马丁
在线博客:https://open8gu.com
大话面试,技术同学面试必备的八股文小册,以精彩回答应对深度问题,助力你在面试中拿个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
注解自带 name
和 type
两个属性,这决定了 @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
,并最终完成注入。