一文搞懂Spring @Autowired注解的使用及其原理
温馨提示:这篇文章已超过387天没有更新,请注意相关的内容是否还可用!
一、全文概览
依赖注入(DI)是Spring核心特性之一,而@Autowired也是我们日常高频使用的Spring依赖注入方式之一,因此有必要对它的使用以及原理做一个全面的掌握。本文从@Autowired使用、原理入手记录,并扩展延伸Spring中其他具备注入功能的注解。
二、@Autowired简介与使用
1、简介
我们直接通Autowired注解源码来看下该注解的简介
// 可以标注在构造器、方法、参数、字段、注解类型(做为元注解)上
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
// 运行时注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* 声明该注解标注的依赖是否需要一定存在于Spring容器中
* true为必须存在,如果不存在的话就抛出NoSuchBeanDefinitionException异常
* false不要求必须存在,如果不存在也不抛出异常(一般不建议设置,可能会引发线上事故)
* Defaults to {@code true}.
*/
boolean required() default true;
}
通过上面代码我们可以看出@Autowired可以标注在构造器、方法、参数、字段以及派生注解上,所以注入时机非常多,可以准确的控制在何时、何处注入以及如何注入。
2、使用
我们先来学习下关于@Autowired的使用方式:
Bean配置类
public class BeanConfiguration {
@Bean
public User user() {
return new User("markus", 24);
}
}
演示类
package com.markus.spring.injection;
import com.markus.spring.annotation.MyAutowired;
import com.markus.spring.bean.User;
import com.markus.spring.configuration.BeanConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import java.util.Collection;
import java.util.Map;
/**
* @author: markus
* @date: 2023/2/5 10:43 PM
* @Description: @Autowired注解示例
* @Blog: https://markuszhang.com
* It's my honor to share what I've learned with you!
*/
// 导入Bean配置
@Import({
com.markus.spring.configuration.BeanConfiguration.class
})
public class AutowiredAnnotationDependencyInjectionDemo {
@Autowired
private User user;
@Autowired
private Map userMap;
@Autowired
private Collection userCollection;
private User userFromCtor;
// @Autowired 可标注在构造器或者构造器的参数里面,两者取其一即可
public AutowiredAnnotationDependencyInjectionDemo(@Autowired User user) {
this.userFromCtor = user;
}
private User userFromMethod;
@Autowired
public void autowiredUser(User user) {
this.userFromMethod = user;
}
@MyAutowired
private User userFromCustomAnnotation;
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AutowiredAnnotationDependencyInjectionDemo.class);
context.refresh();
AutowiredAnnotationDependencyInjectionDemo demo = context.getBean(AutowiredAnnotationDependencyInjectionDemo.class);
System.out.println("demo.user : " + demo.user);
System.out.println("demo.userMap : " +demo.userMap);
System.out.println("demo.userCollection : " +demo.userCollection);
System.out.println("demo.userFromCtor : " +demo.userFromCtor);
System.out.println("demo.userFromMethod : " +demo.userFromMethod);
System.out.println("demo.userFromCustomAnnotation : " +demo.userFromCustomAnnotation);
context.close();
}
}
控制台结果
当Spring容器中有多个相同类型的Bean时,它还可以与@Qualifier配合使用来指定某一特定的Bean
Bean配置
/**
* @author: markus
* @date: 2023/2/11 4:49 PM
* @Description: 相同类型多个Bean配置
* @Blog: https://markuszhang.com
* It's my honor to share what I've learned with you!
*/
public class SameTypeBeanConfiguration {
@Bean
public User user1() {
return new User("markus", 24);
}
@Bean
public User user2() {
return new User("Luna", 23);
}
}
演示类
package com.markus.spring.injection;
import com.markus.spring.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
/**
* @author: markus
* @date: 2023/2/11 4:47 PM
* @Description:
* @Blog: https://markuszhang.com
* It's my honor to share what I've learned with you!
*/
@Import({
com.markus.spring.configuration.SameTypeBeanConfiguration.class
})
public class QualifierAnnotationUseDemo {
@Autowired
@Qualifier(value = "user1")
private User user;
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(QualifierAnnotationUseDemo.class);
context.refresh();
QualifierAnnotationUseDemo demo = context.getBean(QualifierAnnotationUseDemo.class);
System.out.println("demo.user : " + demo.user);
context.close();
}
}
控制台
三、@Autowired原理
1、Bean的生命周期
在讲解@Autowired原理之前,有必要先提及一下Bean的生命周期,但在这里不做过多叙述,只是让大家有个大致的认识,以及@Autowired在哪里开始发挥作用的。
上图为Spring Bean的整个的一个生命周期,包括定义Bean配置信息、加载解析并注册Bean元信息,在我们程序运行时getBean获取Spring Bean又会经过Bean的实例化、属性赋值、初始化等环节,在这些环节前后,Spring也给了我们一些扩展机会,例如实例化前后、属性赋值前、初始化前、初始化后。因为Spring 单例Bean的生命周期是交给容器去管理的,所以Bean的销毁最后也依赖于容器的销毁,当容器发出销毁消息时,会触发Bean的销毁逻辑,这是我们也可以在Bean销毁前做一些自定义操作。至此就是关于Spring Bean生命周期的一个大体介绍。
那么@Autowired到底发生在哪个阶段呢?我们接下来再来分析下BeanFactory#getBean的内部大致流程!
上图中标红的备注中正是@Autowired发挥作用的环节。Bean生命周期后续会单独写一篇文章,这里就不做展开了,我们把关注点聚焦到@Autowired实现细节上去!
2、@Autowired实现细节
通过Bean生命周期概览,我们知道如果想要挖掘@Autowired实现的原理,我们先要去了解两个类:
- AbstractAutowiredCapableBeanFactory
- AutowiredAnnotationBeanPostProcessor
1、AbstractAutowiredCapableBeanFactory
我们通过IDEA定位到AbstractAutowiredCapableBeanFactory这个类的doCreateBean方法,在这个方法里面我们关注两个函数:
- applyMergerBeanDefinitionPostProcessors 它是spring提供给用户or框架内部的有关post-processors去修改合并BeanDefinition的机会
- populateBean 它是spring给bean进行属性赋值的函数入口
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { // xxx } } try { populateBean(beanName, mbd, instanceWrapper); } catch (Throwable ex) { // xxx } return exposedObject; }通过doCreateBean函数进入到applyMergedBeanDefinitionPostProcessors方法,来看看其内部做了哪些事情:
- 它其实就做了一件事:拿到容器中的BeanPostProcessor集合并遍历,寻找属于MergedBeanDefinitionPostProcessor的BeanPostProcessor,并执行bdp.postProcessorMergedBeanDefinition后置处理方法
- AutowiredAnnotationBeanPostProcessor正是MergedBeanDefinitionPostProcessor的一个派生子类,稍后我们介绍该类的时候提及这个方法的细节
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }返回到doCreateBean函数并进入到populateBean方法,抛出非核心的代码逻辑,我们可以看到该函数内部一共有四大核心逻辑处理:
- 获取InstantiationAwareBeanPostProcessor集合并遍历执行其PostProcessAfterInstantiation后处理方法,意在执行bean实例化后、属性赋值前的一些扩展逻辑
- 解析bean元信息配置的依赖注入模型mbd.getResolvedAutowireMode,这里通常是有xml bean配置的autowire指定
- 这里处理byName和byType,constructor是通过实例创建的时候被处理的
- 获取InstantiationAwareBeanPostProcessor集合并遍历执行其postProcessProperties方法,这里也就是@Autowired注解进行依赖注入的时机,在AutowiredAnnotationBeanPostProcessor我们会提及这个方法的细节
- 最后将PropertyValues的内容注入到最终的Bean实例相应的字段中(这块用于xml配置的字段设置)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); pvs = pvsToUse; } } } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }2、AutowiredAnnotationBeanPostProcessor
通过Bean生命周期概览,我们可以知道@Autowired是在Bean属性赋值阶段将依赖Bean注入到当前Bean字段中的,实现类是AutowiredAnnotationBeanPostProcessor,我们先来了解下它的继承结构并解释它的相关功能
看到上图的继承结构可以发现其实AutowiredAnnotationBeanPostProcessor具备两方面的功能,一方面是InstantiationAwareBeanPostProcessor在Bean实例化前后以及属性赋值前做些扩展;另一方面是在合并BeanDefinition后做些扩展,所谓“合并BeanDefinition”就是将配置的子BeanDefinition和父BeanDefinition合并形成当前Bean的最终BeanDefinition配置元信息,这里给大家举个具体例子:
我们先来看下AutowiredAnnotationBeanPostProcessor的构造器,可以看出它是@Autowired、@Value以及jsr-330的@Inject注解的实现,我们本节主要分析@Autowired注解的实现原理。
public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class






