@Autowired注解的使用及源码解析

@Autowired的几种用法

  • 作用在属性上
  • 作用在方法上
  • 作用在构造器上

demo演示

创建三个普通bean

@Component
public class ComponentA {
}

@Component
public class ComponentB {
}

@Component
public class ComponentC {
}

依赖注入

package com.test.model.component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MixComponent {

    @Autowired
    private ComponentA componentA;

    private ComponentB componentB;

    private ComponentC componentC;

    @Autowired
    public void setComponentB(ComponentB componentB) {
        this.componentB = componentB;
    }

    public MixComponent() {
    }

    @Autowired
    public MixComponent(ComponentC componentC) {
        this.componentC = componentC;
    }
}

源码解析

前置知识

1.处理@Autowired的后置处理器是AutowiredAnnotationBeanPostProcessor

2.各个后置处理器会在bean的实例化过程中执行特定的方法,执行顺序如下

  1. postProcessBeforeInstantiation
  2. postProcessMergedBeanDefinition
  3. postProcessAfterInstantiation 
  4. postProcessProperties
  5. postProcessBeforeInitialization
  6. postProcessAfterInitialization

3.AutowiredAnnotationBeanPostProcessor一些重要方法的作用,及相关源码截图

  1. determineCandidateConstructors : 推断构造方法
  2. postProcessMergedBeanDefinition : 发现注入点
  3. postProcessProperties : 属性注入

 推断构造方法相关博文 : Spring之推断构造方法

发现注入点

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata

AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    // 判断class是否存在@Autowired、@Value注解,如果不存在,直接就不处理
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }

    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // 获取field上@Autowired、@Value注解信息
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                // 如果field是static则不处理
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                // 判断是否必须
                // @Autowired注解:属性required == true表示必须
                // @Value注解:必须
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
            }
        });

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            // 获取method上@Autowired、@Value注解信息
            MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                // 如果method是static则不处理
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                // 如果method参数个数是0则不处理
                if (method.getParameterCount() == 0) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation should only be used on methods with parameters: " +
                                method);
                    }
                }
                // 判断是否必须
                // @Autowired注解:属性required == true表示必须
                // @Value注解:必须
                boolean required = determineRequiredStatus(ann);

                // 如果方法是setXxx或者getXxx,则利用Spring自省机制获取PropertyDescriptor对象
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);

                currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return InjectionMetadata.forElements(elements, clazz);
}

 小结

如果field或者method上存在@Autowired或者@Value注解,则Spring会将其解析成一个注入点。field会被解析成AutowiredFieldElement,method会被解析成AutowiredMethodElement

注意点

  • field或者method不能是static,否则不处理
  • method的参数个数必须大于0

属性注入

AutowiredAnnotationBeanPostProcessor#postProcessProperties

注意这里的metadata不是我们方法点进去的InjectionMetadata,而是AutowiredAnnotationBeanPostProcessor的内部类

  • AutowiredFieldElement
  • AutowiredMethodElement

AutowiredFieldElement#inject

AutowiredMethodElement#inject

Field注入

AutowiredAnnotationBeanPostProcessor#resolveFieldValue

DefaultListableBeanFactory#resolveDependency

DefaultListableBeanFactory#doResolveDependency

Spring中细节一般都是在doXxx这样的方法中,所以我们要重点关注

1.处理@Value注解

 大概有下列几种用法

  • @Value("${xxx}") : 获取当前环境中名称为xxx的属性值
  • @Value("${xxx:8080}") : 获取当前环境中名称为xxx的属性值,如果不存在,使用默认值8080
  • @Value("${${xxx}}") :假设当前环境中属性xxx的值为yyy,则表达式获取的为环境中名称为yyy的属性值
  • @Value("#{xxx}") : 获取当前容器中名称为xxx的bean

@Value相关博文 : Spring之@Value注解

2.处理集合类依赖

集合类依赖的处理过程我们不重点说明,因为其底层也是调用单体依赖的逻辑,主要演示其用法

创建一个接口和实现其接口的两个bean

public interface Animal {
}

@Component
public class Cat implements Animal {
}

@Component
public class Fish implements Animal {
}

创建类型为House的bean

@Component
public class House {

    @Autowired
    private List<Animal> list;

    @Autowired
    private Map<String, Animal> map;

    @Autowired
    private Animal[] array;
}

查看运行结果

3.处理单体依赖

DefaultListableBeanFactory#findAutowireCandidates

注入特定类型的bean

Spring期望你在注入某些特定类型的bean时候,使用的是它预先设置的bean,而不是用户自定义的bean

相关源码AbstractApplicationContext#prepareBeanFactory

 demo演示

@Component
public class Person {
    
    // 这种情况下会注入Spring容器中的beanFactory
    @Autowired
    private BeanFactory beanFactory;
    
}
添加候选者

什么是SelfReference

@Configuration
public class SelfReference {
    
    // 第一种情况下的selfReference
    @Autowired
    private SelfReference selfReference;

    // 第二种情况下的selfReference
    @Autowired
    private InnerReference innerReference;

    @Bean
    public InnerReference innerReference() {
        return new InnerReference();
    }

    static class InnerReference {

    }
}

isAutowireCandidate

isAutowireCandidate的方法调用栈有很多同名方法,我们分析最核心的一个

DefaultListableBeanFactory#isAutowireCandidate

这里的resolver是的类型是QualifierAnnotationAutowireCandidateResolver

查看类结构

  1. SimpleAutowireCandidateResolver : 判断bd是否是isAutowireCandidate
  2. GenericTypeAwareAutowireCandidateResolver : 处理泛型
  3. QualifierAnnotationAutowireCandidateResolver : 处理@Qualifier注解

BeanDefinitionHolder对象必须满足上述三个类的isAutowireCandidate方法都返回true,才表示此BeanDefinitionHolder对象是一个候选bd

演示SimpleAutowireCandidateResolver#isAutowireCandidate返回false的情况

创建一个类型为Foo的bean,并复用上文代码

@Component
public class Foo {

}

@Component
public class Person {

    // 这种情况下会注入Spring容器中的beanFactory
    @Autowired
    private BeanFactory beanFactory;

    @Autowired(required = false)
    private Foo foo;
}

创建一个bfpp,将foo的AutowireCandidate的值设为false

@Component
public class FirstBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        BeanDefinition beanDefinition = registry.getBeanDefinition("foo");
        // 设置其不是候选者
        beanDefinition.setAutowireCandidate(false);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

属性foo注入失败

演示会校验泛型的情况

创建Book类,以及实现该类的两个bean

public class Book {
}

@Component
public class EnglishBook extends Book{
}

@Component
public class MathBook extends Book{
}

改造Person代码

@Component
public class Person {
    
    @Autowired
    private List<? extends Book> books;
}

处理@Qualifier注解

@Qualifier相关博文 : Spring之@Qualifier注解

推断候选者

DefaultListableBeanFactory#determineAutowireCandidate

    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        // 如果仅有一个候选者所属class上存在@Primary注解,则返回该候选者
        // 如果存在多个候选者所属class上存在@Primary注解,则抛出异常
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }

        // 判断候选者所属class上是否存在注解@Priority注解
        // 如果存在,返回优先级最高的候选者
        String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        }
        
        // 判断候选者的candidateName和属性名称是否一致,如果一致返回该候选者
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateName = entry.getKey();
            Object beanInstance = entry.getValue();
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }

测试代码 

@Component
public class TestBean {

    @Autowired
    private PrimaryTest primaryTest;

    @Autowired
    private PriorityTest priorityTest;

    @Autowired
    private BeanNameTest secondBeanName;
}

public interface PrimaryTest {
}

@Component
@Primary
public class FirstPrimaryBean implements PrimaryTest {
}

@Component
public class SecondPrimaryBean implements PrimaryTest {
}

public interface PriorityTest {
}

@Component
@Priority(1)
public class FirstPriorityBean implements PriorityTest {
}

@Component
@Priority(2)
public class SecondPriorityBean implements PriorityTest {
}

public interface BeanNameTest {
}

@Component
public class FirstBeanName implements BeanNameTest {
}

@Component
public class SecondBeanName implements BeanNameTest {
}

查看运行结果

Method注入

方法的注入和属性的注入类似,主要还是doResolveDependency方法,这里就不再赘述

整体流程

相关推荐

  1. SpringBoot

    2024-03-23 16:06:01       41 阅读
  2. ConcurrentHashMap

    2024-03-23 16:06:01       41 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-23 16:06:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-23 16:06:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-23 16:06:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-23 16:06:01       18 阅读

热门阅读

  1. css的text-shadow详解

    2024-03-23 16:06:01       17 阅读
  2. css的border详解

    2024-03-23 16:06:01       18 阅读
  3. Spring Boot(七十一):整合RateLimiter实现接口限流

    2024-03-23 16:06:01       17 阅读
  4. 从展望未来的方向思考,AI程序员对现状的影响

    2024-03-23 16:06:01       18 阅读
  5. PVE 缩小LXC中 RAW 格式磁盘

    2024-03-23 16:06:01       15 阅读
  6. 学习 zustand

    2024-03-23 16:06:01       17 阅读
  7. 前端面试-手搓代码篇

    2024-03-23 16:06:01       17 阅读
  8. 构造函数(原型和原型链)

    2024-03-23 16:06:01       16 阅读
  9. SpringDataJpa大坑——一对多级联修改问题

    2024-03-23 16:06:01       13 阅读
  10. v-for=“item in arr“ 的理解

    2024-03-23 16:06:01       17 阅读