Spring IoC源码学习:@Autowire 详解

目录

Spring IoC源码学习全系列

前言

如何使用

1.开启注解配置

2.在代码中使用

继承结构

源码解析

AutowiredAnnotationBeanPostProcessor 何时被注册到 BeanFactory?

AnnotationConfigUtils#registerAnnotationConfigProcessors

构造函数注入时做了什么

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

代码块1:findAutowiredAnnotation

属性注入时做了什么

1.postProcessMergedBeanDefinition 方法介绍

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

代码块2:findAutowiringMetadata

代码块3:buildAutowiringMetadata

代码块4:checkConfigMembers

2.postProcessPropertyValues 方法介绍

AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 

代码块5:inject

代码块6:AutowiredFieldElement#inject

代码块7:registerDependentBeans

总结

相关文章


Spring IoC源码学习全系列

小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习:ApplicationContext 刷新前的配置

Spring IoC源码学习:obtainFreshBeanFactory详解

Spring IoC源码学习:parseDefaultElement详解

Spring IoC源码学习:parseCustomElement详解

Spring IoC源码学习:obtainFreshBeanFactory详解

Spring IoC源码学习:invokeBeanFactoryPostProcessors详解

Spring IoC源码学习:registerBeanPostProcessors详解

Spring IoC源码学习:finishBeanFactoryInitialization详解

Spring IoC源码学习:getBean详解

Spring IoC源码学习:createBean详解(上)

Spring IoC源码学习:createBean详解(下)

Spring IoC源码学习:@Autowire 详解

Spring IoC源码学习:finishRefresh 详解

 

前言

在 Spring IoC:createBean 详解(上)代码块4.5 和 Spring IoC:createBean详解(下)代码块1代码块4的 7.1.1 我们遗留了一个解析——@Autowire 注解的解析。之所以单独提出来,是因为在我现在接触的项目中,使用 @Autowire 注解的比例非常高,可以说基本用过 Spring 的同学都接触过这个注解,重要性不言而喻。因此,单独拿出来,较详细的介绍一下。

本文只会单独介绍 @Autowire 的部分内容,具体 @Autowire 注解的完整过程,需要结合 Spring IoC:createBean 详解(上)代码块4.5 和 Spring IoC:createBean详解(下)代码块1代码块4的 7.1.1 去看。

 

如何使用

1.开启注解配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <!-- component-scan包含了annotation-config的效果 -->
    <context:component-scan base-package="com.joonwhee.open.demo.service"/>
    <context:annotation-config/>
</beans>

要使用 @Autowire 注解,可以通过 <context:component-scan /> 或 <context:annotation-config/> 来开启,其中前者是包含了后者的效果的,因此现在一般都使用 <context:component-scan /> 即可。

2.在代码中使用

@Service
public class ConstructorServiceImpl implements ConstructorService {

    // 1.属性注入
    @Autowired
    private UserService userService;

    private final DemoService demoService;

    // 2.构造函数注入
    @Autowired
    public ConstructorServiceImpl(DemoService demoService) {
        this.demoService = demoService;
    }
}

该代码中使用了目前最常见的两种注入方式:1)属性注入;2)构造函数注入。

以我自己为例,我周围最常用的是:属性注入,但是 Spring 团队建议使用的方式是:构造函数注入,当你使用属性注入时,鼠标移到属性上的 @Autowire 就可以看到如下图的提示,并且可以通过快捷键将属性注入直接修改成构造函数注入。

构造函数的常见优点是:

  1. 保证依赖不可变(final 关键字)
  2. 保证依赖不为空(省去了检查)
  3. 以完全初始化的状态返回到客户端(调用)代码
  4. 避免了循环依赖
  5. 提升了代码的可复用性

构造函数的常见缺点是:

  1. 构造函数会有很多参数。
  2. 有些类是需要默认构造函数的,一旦使用构造函数注入,就无法使用默认构造函数。
  3. 这个类里面的有些方法并不需要用到这些依赖。

这些优点我看了下,个人觉得还好,只要不瞎用,其实使用属性注入并不会有什么问题。至于使用哪一种,就看个人喜好了。

 

继承结构

@Autowire 注解的功能实现都是由 AutowiredAnnotationBeanPostProcessor 实现,AutowiredAnnotationBeanPostProcessor 的继承关系如下图:

 

源码解析

AutowiredAnnotationBeanPostProcessor 何时被注册到 BeanFactory?

在 Spring IoC:context:component-scan节点详解 中的代码块17就有 AutowiredAnnotationBeanPostProcessor 被注册到 BeanFactory 的代码,如下:

 

AnnotationConfigUtils#registerAnnotationConfigProcessors

查看该方法的上下文,请参考:Spring IoC:context:component-scan节点详解 中的代码块17

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 1.设置dependencyComparator属性
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);

    // 3.注册内部管理的用于处理@Configuration注解的后置处理器的bean
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // 3.1 registerPostProcessor: 注册BeanDefinition到注册表中
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 4.注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的bean
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 5.注册内部管理的用于处理@Required注解的后置处理器的bean
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 6.注册内部管理的用于处理JSR-250注解(例如@Resource, @PostConstruct, @PreDestroy)的后置处理器的bean
    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 7.注册内部管理的用于处理JPA注解的后置处理器的bean
    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 8.注册内部管理的用于处理@EventListener注解的后置处理器的bean
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    // 9.注册内部管理用于生产ApplicationListener对象的EventListenerFactory对象
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

在该代码的第4点注册了 AutowiredAnnotationBeanPostProcessor,具体看 registerAnnotationConfigProcessors 方法的调用方,可以看到 AnnotationConfigBeanDefinitionParser 和 ComponentScanBeanDefinitionParser,而这两个正是 <context:component-scan /> 和 <context:annotation-config/> 的 bean 定义解析器。

 

构造函数注入时做了什么

构造函数注入通常来说有两种:1)xml 配置注入;2)@Autowire 注解注入;本文只讨论 @Autowire 注解注入。

AutowiredAnnotationBeanPostProcessor 中重写的方法不多,直接找一下就可以找到跟构造函数相关的方法:determineCandidateConstructors,该方法被定义在 SmartInstantiationAwareBeanPostProcessor 接口中,主要作用是:确定要用于给定 bean 的候选构造函数。

在 Spring IoC 的过程中,调用的入口在 Spring IoC:createBean详解(上)中的代码块4.5,下面介绍下 determineCandidateConstructors 方法。

 

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

查看该方法的上下文,请参考:Spring IoC:createBean详解(上)中的代码块4.5

@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
        throws BeanCreationException {

    // Let's check for lookup methods here..
    // @Lookup注解检查
    if (!this.lookupMethodsChecked.contains(beanName)) {
        try {
            ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    Lookup lookup = method.getAnnotation(Lookup.class);
                    if (lookup != null) {
                        LookupOverride override = new LookupOverride(method, lookup.value());
                        try {
                            RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
                            mbd.getMethodOverrides().addOverride(override);
                        } catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(beanName,
                                    "Cannot apply @Lookup to beans without corresponding bean definition");
                        }
                    }
                }
            });
        } catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
        } catch (NoClassDefFoundError err) {
            throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
                    "] for lookup method metadata: could not find class that it depends on", err);
        }
        // 已经检查过的添加到lookupMethodsChecked
        this.lookupMethodsChecked.add(beanName);
    }

    // Quick check on the concurrent map first, with minimal locking.
    // 1.构造函数解析,首先检查是否存在于缓存中
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // Fully synchronized resolution now...
        // 2.加锁进行操作
        synchronized (this.candidateConstructorsCache) {
            // 3.再次检查缓存,双重检测
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                // 存放原始的构造函数(候选者)
                Constructor<?>[] rawCandidates;
                try {
                    // 4.获取beanClass声明的构造函数(如果没有声明,会返回一个默认的无参构造函数)
                    rawCandidates = beanClass.getDeclaredConstructors();
                } catch (Throwable ex) {
                    throw new BeanCreationException(beanName,
                            "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                    "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
                // 存放使用了@Autowire注解的构造函数
                List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
                // 存放使用了@Autowire注解,并且require=true的构造函数
                Constructor<?> requiredConstructor = null;
                // 存放默认的构造函数
                Constructor<?> defaultConstructor = null;
                // 5.遍历原始的构造函数候选者
                for (Constructor<?> candidate : rawCandidates) {
                    // 6.获取候选者的注解属性
                    AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                    if (ann == null) {
                        // 7.如果没有从候选者找到注解,则尝试解析beanClass的原始类(针对CGLIB代理)
                        Class<?> userClass = ClassUtils.getUserClass(beanClass);
                        if (userClass != beanClass) {
                            try {
                                Constructor<?> superCtor =
                                        userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                ann = findAutowiredAnnotation(superCtor);
                            } catch (NoSuchMethodException ex) {
                                // Simply proceed, no equivalent superclass constructor found...
                            }
                        }
                    }
                    // 8.如果该候选者使用了@Autowire注解
                    if (ann != null) {
                        if (requiredConstructor != null) {
                            // 8.1 之前已经存在使用@Autowired(required = true)的构造函数,则不能存在其他使用@Autowire注解的构造函数,否则抛异常
                            throw new BeanCreationException(beanName,
                                    "Invalid autowire-marked constructor: " + candidate +
                                            ". Found constructor with 'required' Autowired annotation already: " +
                                            requiredConstructor);
                        }
                        // 8.2 获取注解的require属性值
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            if (!candidates.isEmpty()) {
                                // 8.3 如果当前候选者是@Autowired(required = true),则之前不能存在其他使用@Autowire注解的构造函数,否则抛异常
                                throw new BeanCreationException(beanName,
                                        "Invalid autowire-marked constructors: " + candidates +
                                                ". Found constructor with 'required' Autowired annotation: " +
                                                candidate);
                            }
                            // 8.4 如果该候选者使用的注解的required属性为true,赋值给requiredConstructor
                            requiredConstructor = candidate;
                        }
                        // 8.5 将使用了@Autowire注解的候选者添加到candidates
                        candidates.add(candidate);
                    } else if (candidate.getParameterTypes().length == 0) {
                        // 8.6 如果没有使用注解,并且没有参数,则为默认的构造函数
                        defaultConstructor = candidate;
                    }
                }
                // 9.如果存在使用了@Autowire注解的构造函数
                if (!candidates.isEmpty()) {
                    // Add default constructor to list of optional constructors, as fallback.
                    // 9.1 但是没有使用了@Autowire注解并且required属性为true的构造函数
                    if (requiredConstructor == null) {
                        if (defaultConstructor != null) {
                            // 9.2 如果存在默认的构造函数,则将默认的构造函数添加到candidates
                            candidates.add(defaultConstructor);
                        } else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                            logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
                                    "': single autowire-marked constructor flagged as optional - " +
                                    "this constructor is effectively required since there is no " +
                                    "default constructor to fall back to: " + candidates.get(0));
                        }
                    }
                    // 9.3 将所有的candidates当作候选者
                    candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
                } else if (rawCandidates.length == 1 && rawCandidates[0].getParameterTypes().length > 0) {
                    // 10.如果candidates为空 && beanClass只有一个声明的构造函数(非默认构造函数),则将该声明的构造函数作为候选者
                    candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
                } else {
                    // 11.否则返回一个空的Constructor对象
                    candidateConstructors = new Constructor<?>[0];
                }
                // 12.将beanClass的构造函数解析结果放到缓存
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }
    // 13.返回解析的构造函数
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

6.获取候选者的注解属性,见代码块1详解

关于 8.1 和 8.3 的异常校验,说的简单点:在一个 bean 中,只要有构造函数使用了 “@Autowired(required = true)” 或 “@Autowired”,就不允许有其他的构造函数使用 “@Autowire”;但是允许有多个构造函数同时使用 “@Autowired(required = false)”。

 

代码块1:findAutowiredAnnotation

private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
    // 1.判断ao是否有被注解修饰
    if (ao.getAnnotations().length > 0) {
        // 2.检查是否有autowiredAnnotationTypes中的注解:@Autowired、@Value(@Value无法修饰构造函数)
        for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
            // 3.拿到注解的合并注解属性,@Autowire在这边拿到,required=true(默认属性)
            AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
            if (attributes != null) {
                return attributes;
            }
        }
    }
    return null;
}

确定了要用于给定 bean 的候选构造函数后,之后的逻辑就是执行构造函数自动注入,该逻辑在 Spring IoC:createBean 详解(上)中的代码块5已经介绍。

 

属性注入时做了什么

属性注入通常来说有两种:1)xml 配置注入;2)@Autowire 注解注入;本文只讨论 @Autowire 注解注入。

AutowiredAnnotationBeanPostProcessor 中跟属性注入有关的方法出口有两个:postProcessMergedBeanDefinition 和 postProcessPropertyValues。

 

1.postProcessMergedBeanDefinition 方法介绍

postProcessMergedBeanDefinition 被定义在 MergedBeanDefinitionPostProcessor 接口中,该方法的主要作用是:对指定 bean 的给定 MergedBeanDefinition 进行后置处理。

在 AutowiredAnnotationBeanPostProcessor 的实现中,主要是对使用了 @Autowire 注解的方法和属性进行预解析,并放到 injectionMetadataCache 缓存中,用于后续使用。

在 Spring IoC 的过程中,调用的入口在:Spring IoC:createBean详解(下)中的代码块1,下面介绍下 postProcessMergedBeanDefinition 方法。

 

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

查看该方法的上下文,请参考:Spring IoC:createBean详解(下)中的代码块1

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    if (beanType != null) {
        // 1.在指定Bean中查找使用@Autowire注解的元数据
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        // 2.检查元数据中的注解信息
        metadata.checkConfigMembers(beanDefinition);
    }
}

1.在指定 bean 中查找使用 @Autowire 注解的元数据,见代码块2详解

2.检查元数据中的注解信息,见代码块4详解。

 

代码块2:findAutowiringMetadata

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    // 1.设置cacheKey的值(beanName 或者 className)
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    // 2.检查beanName对应的InjectionMetadata是否已经存在于缓存中
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    // 3.检查InjectionMetadata是否需要刷新(为空或者class变了)
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            // 4.加锁后,再次从缓存中获取beanName对应的InjectionMetadata
            metadata = this.injectionMetadataCache.get(cacheKey);
            // 5.加锁后,再次检查InjectionMetadata是否需要刷新
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    // 6.如果需要刷新,并且metadata不为空,则先移除
                    metadata.clear(pvs);
                }
                try {
                    // 7.解析@Autowired注解的信息,生成元数据(包含clazz和clazz里解析到的注入的元素,
                    // 这里的元素包括AutowiredFieldElement和AutowiredMethodElement)
                    metadata = buildAutowiringMetadata(clazz);
                    // 8.将解析的元数据放到injectionMetadataCache缓存,以备复用,每一个类只解析一次
                    this.injectionMetadataCache.put(cacheKey, metadata);
                } catch (NoClassDefFoundError err) {
                    throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
                            "] for autowiring metadata: could not find class that it depends on", err);
                }
            }
        }
    }
    return metadata;
}

7.解析 @Autowired 注解的信息,生成元数据,见代码块3详解

 

代码块3:buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    // 1.用于存放所有解析到的注入的元素的变量
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
    Class<?> targetClass = clazz;

    // 2.循环遍历
    do {
        // 2.1 定义存放当前循环的Class注入的元素(有序)
        final LinkedList<InjectionMetadata.InjectedElement> currElements =
                new LinkedList<InjectionMetadata.InjectedElement>();

        // 2.2 如果targetClass的属性上有@Autowired注解,则用工具类获取注解信息
        ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                // 2.2.1 获取field上的@Autowired注解信息
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    // 2.2.2 校验field是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的field
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
                    // 2.2.3 获取@Autowired注解的required的属性值(required:值为true时,如果没有找到bean时,自动装配应该失败;false则不会)
                    boolean required = determineRequiredStatus(ann);
                    // 2.2.4 将field、required封装成AutowiredFieldElement,添加到currElements
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            }
        });

        // 2.3 如果targetClass的方法上有@Autowired注解,则用工具类获取注解信息
        ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
            @Override
            public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                // 2.3.1 找到桥接方法
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                // 2.3.2 判断方法的可见性,如果不可见则直接返回
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    return;
                }
                // 2.3.3 获取method上的@Autowired注解信息
                AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    // 2.3.4 校验method是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的method
                    if (Modifier.isStatic(method.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static methods: " + method);
                        }
                        return;
                    }
                    // 2.3.5 @Autowired注解标识在方法上的目的就是将容器内的Bean注入到方法的参数中,没有参数就违背了初衷
                    if (method.getParameterTypes().length == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                        }
                    }
                    // 2.3.6 获取@Autowired注解的required的属性值
                    boolean required = determineRequiredStatus(ann);
                    // 2.3.7  获取method的属性描述器
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    // 2.3.8 将method、required、pd封装成AutowiredMethodElement,添加到currElements
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            }
        });

        // 2.4 将本次循环获取到的注解信息添加到elements
        elements.addAll(0, currElements);
        // 2.5 在解析完targetClass之后,递归解析父类,将所有的@Autowired的属性和方法收集起来,且类的层级越高其属性会被越优先注入
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class); // 2.6 递归解析targetClass父类(直至父类为Object结束)

    // 2.7 将clazz和解析到的注入的元素封装成InjectionMetadata
    return new InjectionMetadata(clazz, elements);
}

2.2.1 获取 field 上的 @Autowired 注解信息、2.3.3 获取 method 上的 @Autowired 注解信息,见代码块1详解

 

代码块4:checkConfigMembers

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size());
    // 1.遍历检查所有要注入的元素
    for (InjectedElement element : this.injectedElements) {
        Member member = element.getMember();
        // 2.如果beanDefinition的externallyManagedConfigMembers属性不包含该member
        if (!beanDefinition.isExternallyManagedConfigMember(member)) {
            // 3.将该member添加到beanDefinition的externallyManagedConfigMembers属性
            beanDefinition.registerExternallyManagedConfigMember(member);
            // 4.并将element添加到checkedElements
            checkedElements.add(element);
            if (logger.isDebugEnabled()) {
                logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
            }
        }
    }
    // 5.赋值给checkedElements(检查过的元素)
    this.checkedElements = checkedElements;
}

 

至此,使用 @Autowire 修饰的方法和属性的相关元数据信息都已经放到 injectionMetadataCache 缓存中,用于后续使用。

 

2.postProcessPropertyValues 方法介绍

postProcessPropertyValues 被定义在 InstantiationAwareBeanPostProcessor 接口中,该方法的主要作用是:将属性值应用于给定 bean 之前对给定属性值进行后置处理。

在 AutowiredAnnotationBeanPostProcessor 的实现中,主要是对使用了 @Autowire 注解的方法和属性进行自动注入,将依赖的 bean 赋值给对应的属性。

在 Spring IoC 的过程中,调用的入口在:Spring IoC:createBean详解(下)中的代码块4中的7.1.1,下面介绍下 postProcessPropertyValues 方法。

 

AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 

查看该方法的上下文,请参考:Spring IoC:createBean详解(下)中的代码块4中的7.1.1

@Override
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

    // 1.在指定Bean中查找使用@Autowire注解的元数据
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 2.InjectionMetadata: 执行inject()方法,开始执行属性注入或方法注入
        metadata.inject(bean, beanName, pvs);
    } catch (BeanCreationException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

1.在指定 bean 中查找使用 @Autowire 注解的元数据,见代码块2详解,这边会直接从缓存中拿到之前已经解析好的数据。

2.执行 inject() 方法,开始执行属性注入或方法注入,见代码块5详解

 

代码块5:inject

public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
    // 1.如果checkedElements存在,则使用checkedElements,否则使用injectedElements
    Collection<InjectedElement> elementsToIterate =
            (this.checkedElements != null ? this.checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        boolean debug = logger.isDebugEnabled();
        for (InjectedElement element : elementsToIterate) {
            if (debug) {
                logger.debug("Processing injected element of bean '" + beanName + "': " + element);
            }
            // 2.解析@Autowired注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,
            // 这两个类继承InjectionMetadata.InjectedElement,各自重写了inject方法。
            element.inject(target, beanName, pvs);
        }
    }
}

2.解析 @Autowired 注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,这两个类继承InjectionMetadata.InjectedElement,各自重写了 inject 方法。对于属性注入来说,会走到 AutowiredFieldElement 中的 inject 方法,见代码块6详解

 

代码块6:AutowiredFieldElement#inject

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    // 1.拿到该元数据的属性值
    Field field = (Field) this.member;
    Object value;
    // 2.如果缓存中已经存在,则直接从缓存中解析属性
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    } else {
        // 3.将field封装成DependencyDescriptor
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // 4.解析当前属性所匹配的bean实例,并把解析到的bean实例的beanName存储在autowiredBeanNames中
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            if (!this.cached) {
                // 5.value不为空或者required为true
                if (value != null || this.required) {
                    // 6.如果属性依赖注入的bean不止一个(Array,Collection,Map),缓存cachedFieldValue放的是DependencyDescriptor
                    this.cachedFieldValue = desc;
                    // 7.注册依赖关系到缓存(beanName 依赖 autowiredBeanNames)
                    registerDependentBeans(beanName, autowiredBeanNames);
                    // 8.如果属性依赖注入的bean只有一个(正常都是一个)
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        if (beanFactory.containsBean(autowiredBeanName)) {
                            // @Autowired标识属性类型和Bean的类型要匹配,因此Array,Collection,Map类型的属性不支持缓存属性Bean名称
                            // 9.检查autowiredBeanName对应的bean的类型是否为field的类型
                            if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                // 10.将该属性解析到的bean的信息封装成ShortcutDependencyDescriptor,
                                // 以便之后可以通过getBean方法来快速拿到bean实例
                                this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                        desc, autowiredBeanName, field.getType());
                            }
                        }
                    }
                } else {
                    this.cachedFieldValue = null;
                }
                // 11.缓存标识设为true
                this.cached = true;
            }
        }
    }
    if (value != null) {
        // 12.设置字段访问性
        ReflectionUtils.makeAccessible(field);
        // 13.通过反射为属性赋值,将解析出来的bean实例赋值给field
        field.set(bean, value);
    }
}

4.解析当前属性所匹配的 bean 实例,并把解析到的 bean 实例的 beanName 存储在 autowiredBeanNames 中,见 Spring IoC:createBean详解(上)代码块9详解

7.注册依赖关系到缓存(beanName 依赖 autowiredBeanNames),见代码块7详解

13.通过反射为属性赋值,将解析出来的 bean 实例赋值给 field,至此,@Autowire 修饰的 bean 就被注入进来了。

 

代码块7:registerDependentBeans

private void registerDependentBeans(String beanName, Set<String> autowiredBeanNames) {
    if (beanName != null) {
        // 1.遍历所有autowiredBeanNames
        for (String autowiredBeanName : autowiredBeanNames) {
            if (this.beanFactory.containsBean(autowiredBeanName)) {
                // 2.如果autowiredBeanName在BeanFactory中存在,则注册依赖关系到缓存(beanName 依赖 autowiredBeanName)
                this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Autowiring by type from bean name '" + beanName +
                        "' to bean named '" + autowiredBeanName + "'");
            }
        }
    }
}

2.如果 autowiredBeanName 在 BeanFactory 中存在,则注册依赖关系到缓存(beanName 依赖 autowiredBeanName),见 Spring IoC:getBean详解 中代码块7详解

 

总结

本文简单的介绍了 @Autowire 常见的用法,并对 Spring IoC 构建过程 @Autowire 注解相关的方法进行了解析。这些方法如果单独看可能无法很好的理解 @Autowire 注解,建议结合 Spring IoC:createBean 详解(上)和 Spring IoC:createBean详解(下)一起阅读,以便更好的理解 @Autowire 注解的原理。

 

程序员囧辉 CSDN认证博客专家 Spring MySQL 分布式
当你的才华还撑不起你的野心的时候,你就应该静下心来学习,愿你在我这里能有所收获。公众号:程序员囧辉,分享个人在Java学习路上的一些学习、思考、经验和总结。
©️2020 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值