注解说明

@Autowired 是Spring框架的核心注解,用于自动装载构造器、字段、set方法、配置方法上的依赖,它是 JSR-330 @Inject 注解的替代,支持配置 依赖是否必须 选项

属性说明

此注解只有一个属性 required ,默认为 true 表示待注入组件必须存在

注解注入规则说明

构造器注入

  1. 如果一个类声明了多个构造器且没有一个显式标注 @Autowired,则Spring会使用默认的构造方法进行装载
  2. 如果一个类只声明了一个构造器,不管有没有标注 @Autowired 注解它都会被直接使用
  3. 多参数可以配置多个required属性,对于可选注入,可以声明为 Java8 的Optional类型

字段注入

字段在构造器之后,配置方法注入之前进行自动注入

方法注入

方法注入不限制方法名与参数个数,所有参数会被Spring进行匹配注入

参数注入

目前只在 spring-test 模块中有效,其它地方使用会被忽略

数组/集合注入

Spring通过匹配数组/集合的值进行注入,Map的key必须为String类型,支持集合中元素的Order配置

不支持 BeanPostProcessor 或者 BeanFactoryPostProcessor

因为真实的注入动作发生在 BeanPostProcessor 阶段,所以不能在 BeanPostProcessor 或者 BeanFactoryPostProcessor 中使用此注解

源码阅读

在Spring中,处理 @Autowired 注解对应的类为 AutowiredAnnotationBeanPostProcessor ,又是一个Bean后置处理器

对于此类,需要关注其实现的两个接口类 MergedBeanDefinitionPostProcessor (运行时合并Bean的定义回调接口)和 InstantiationAwareBeanPostProcessor (在Bean实例化前后进行处理后置处理器)

  1. MergedBeanDefinitionPostProcessor 主要是为了在真正bean实例化前准备缓存的bean元数据
  2. InstantiationAwareBeanPostProcessor Bean实例化回调接口,通常用于为bean创建代理

测试代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Service
public class MyService {

}

@Controller
public class MyController {

    @Autowired
    MyService myService;

    public void showService() {
        System.out.println("myService = " + myService);
    }
}

@Configuration
@ComponentScan(basePackages = "cn.imcompany.bean.autowired")
public class MyConfiguration {

}

public class Main {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        MyController myController = context.getBean(MyController.class);
        myController.showService();
    }
}

元数据收集

调用栈信息如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
postProcessMergedBeanDefinition:294, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
applyMergedBeanDefinitionPostProcessors:1099, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:575, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:523, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:336, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, AbstractBeanFactory$$Lambda/0x0000007001101000 (org.springframework.beans.factory.support)
getSingleton:288, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:334, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support)
instantiateSingleton:1122, DefaultListableBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingleton:1093, DefaultListableBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:1030, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:987, AbstractApplicationContext (org.springframework.context.support)
refresh:627, AbstractApplicationContext (org.springframework.context.support)
<init>:93, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:19, Main (cn.imcompany.bean.autowired)

由调用栈信息可以发现此动作发生在 finishBeanFactoryInitialization() 阶段, 在doCreateBean方法中被调用

核心逻辑在 buildAutowiringMetadata() 方法中,此方法会循环遍历当前的类及其父类(一直到Object类为止),处理类中的字段与方法是否有需要自动装载的配置,如果有,则会将需要注入的元数据信息存放在 List<InjectionMetadata.InjectedElement> 中返回

在调用方 findAutowiringMetadata() 方法会将返回的元数据信息存入 injectionMetadataCache 中

AutowiredAnnotationBeanPostProcessor能处理哪些注解?

由其构造器逻辑可以发现, AutowiredAnnotationBeanPostProcessor 可以处理:

  1. @Autowired
  2. @Value
  3. @jakarta.inject.Inject
  4. @javax.inject.Inject

注入

自动装配的注入是由 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 来处理(此方法会被AbstractAutowireCapableBeanFactory#populateBean调用),它会先调用 findAutowiringMetadata() 来查询要注入的元数据信息,查到后调用元数据实体InjectionMetadata的inject() 方法,在此方法会遍历当前InjectionMetadata的所有injectedElements元素进行注入操作

支持注入方式: 字段注入(AutowiredFieldElement)与方法注入(AutowiredMethodElement)

第一次由于没有缓存,则会调用 AutowiredFieldElement#resolveFieldValue() 方法(因为测试用例将注解写在了字段上),此方法会调用 DefaultListableBeanFactory#resolveDependency() 对需要注入的bean进行查找解析,找到后会将要注入的bean通过反射设置到当前Class对应字段上。真正的依赖bean解析工作是由 doResolveDependency() 来完成的。

doResolveDependency具体实现步骤:

  1. 使用快捷方式解析,因为实现直接返回null,则继续往下执行
  2. 解析@Value注解上预定义的值或者表达式,由于测试用例未配置,则继续执行
  3. 通过声明的依赖名称进行解析,对于要查找的依赖名称和类型进行判断,满足条件后,则通过调用 getBean() 方法获取依赖的Bean实例,获取成功后则调用 resolveInstance() 直接返回,否则继续执行
  4. 处理多bean,如集合、数组、Map
    1. 特定类型的集合bean匹配(收集装配),有则返回
    2. 直接使用bean定义匹配
  5. 如果匹配到了多个,确定一个,确定不了抛异常
  6. 对单个结果进行检验

本次用例的依赖解析会在第3步中查找完成并进行返回,对于第3步中一个合格的依赖bean需要满足条件如下:

  1. 类型匹配
  2. 是可以注入的候选者
  3. 没有被标注为fallback
  4. 不是primary冲突的bean
  5. 不是自引用

关联注解:

  1. @Primary
  2. @Qulifier
  3. @Order
  4. @Fallback

总结

@Autowired 是Spring框架的核心注解,用于自动注入依赖Bean,可实现对字段、构造器、方法的注入,支持集合类型方式注入。其实现类为 AutowiredAnnotationBeanPostProcessor , Spring解析此注解发生在 refresh 操作的 finishBeanFactoryInitialization 阶段。注入分为两步:

  1. 收集:在构建实例(doCreateBean)时会调用 AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition() 方法来统一对merged bean 定义进行修改,具体实现为遍历当前类以及父类(到Object类为止),判断其定义的字段或者方法上是否标注了此注解,标注则记录其相应的注入信息。
  2. 注入:真正的注入发生在调用 AbstractAutowireCapableBeanFactory#populateBean() ,此方法会调用 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 查询收集的依赖的Bean信息,找到后进行注入,在注入过程中会对候选者进行一系列的条件筛选,满足条件则注入成功

整体流程涉及的核心类调用关系图