SpringBoot源码解析 -- @Value,@Autowired实现原理

SpringBoot深入理解 -- @AliasFor注解的作用
SpringBoot源码解析 -- SpringBoot启动过程
SpringBoot源码解析 -- AutoConfigure的实现原理
SpringBoot源码解析 -- @ComponentScan的实现原理
SpringBoot源码解析 -- @Value,@Autowired实现原理
SpringBoot源码解析 -- Tomcat,SpringMVC启动
SpringBoot源码解析 -- Logging,Environment启动

前面解析@ComponentScan实现原理的文章说了,Spring如何扫描@Component注解的Bean,但扫描的Bean如何注入属性呢?
我们都知道该功能主要使用@Value,@Autowired注解完成,这篇文章主要解析Spring中@Value,@Autowired实现原理。
源码分析基于spring boot 2.1

前面解析Spring注入属性过程的文章中,说过AbstractAutowireCapableBeanFactory#populateBean方法负责注入bean的属性,其实@Value,@Autowired等注解也是在该方法处理。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    ...
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // #1
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }
    ...
}

#1 调用InstantiationAwareBeanPostProcessor#postProcessProperties扩展方法,这里处理@Value,@Autowired等注解。

在解析SpringBoot启动过程的文章中,说过了AutowiredAnnotationBeanPostProcessor负责处理@Value,@Autowired等注解。
(AutowiredAnnotationBeanPostProcessor是InstantiationAwareBeanPostProcessor的实现类)
AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // #1
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);    
    try {
        // #2
        metadata.inject(bean, beanName, pvs);   
    }
    ...
    return pvs;
}

#1 获取Class中关于属性注入相关注解的元数据
#2 完成属性注入操作

AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata -> buildAutowiringMetadata

    private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
        LinkedList elements = new LinkedList();
        Class targetClass = clazz;

        do {
            final LinkedList currElements =
                    new LinkedList();

            ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    // #1
                    AnnotationAttributes ann = findAutowiredAnnotation(field);
                    if (ann != null) {
                        if (Modifier.isStatic(field.getModifiers())) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("Autowired annotation is not supported on static fields: " + field);
                            }
                            return;
                        }
                        boolean required = determineRequiredStatus(ann);
                        currElements.add(new AutowiredFieldElement(field, required));
                    }
                }
            });

            ... // #2

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

        return new InjectionMetadata(clazz, elements);
    }

#1 查找field是否有@Autowired,@Value等注解
#2 查找method是否有@Autowired,@Value等注解

InjectionMetadata#inject方法遍历所有的InjectedElement,调用AutowiredMethodElement,AutowiredFieldElement的inject方法,这里只关注AutowiredFieldElement#inject
InjectionMetadata#inject -> AutowiredFieldElement#inject

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set autowiredBeanNames = new LinkedHashSet(1);
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // #1
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);   
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        ...
    }
    if (value != null) {
        // #2
        ReflectionUtils.makeAccessible(field);  
        field.set(bean, value);
    }
}

#1 根据注解元数据,解析属性值
#2 将解析的结果值注入到bean

DefaultListableBeanFactory#resolveDependency -> DefaultListableBeanFactory#doResolveDependency

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
        Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }

        Class type = descriptor.getDependencyType();
        // #1
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);    
        if (value != null) {
            if (value instanceof String) {
                // #2
                String strVal = resolveEmbeddedValue((String) value);   
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            //#3
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }

        // #4
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);   
        if (multipleBeans != null) {
            return multipleBeans;
        }

        // #5
        Map matchingBeans = findAutowireCandidates(beanName, type, descriptor); 
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        // #6
        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);  
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(type, matchingBeans);
                }
                else {
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            Map.Entry entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        return (instanceCandidate instanceof Class ?
                descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

#1 如果存在@Value注解,获取注解的value值
#2 解析@Value注解的值,如果这里使用占位符引用了配置文件,默认使用PropertyPlaceholderConfigurer#PlaceholderResolvingStringValueResolver解析配置文件中的值。
PropertyPlaceholderConfigurer是一个常用的BeanFactoryPostProcessor,它可以在Spring启动时,将Bean属性配置的占位符解析为配置属性的值
#3 默认使用SimpleTypeConverter将配置值转化为属性要求的类型(例如属性为int类型,则需要将String转换为int类型)
这里最终也会复用TypeConverterDelegate#convertIfNecessary方法。
#4 解析数组、list、map等类型的依赖,使用对应的TypeConverter处理
#5 处理@Autowire,找到候选的bean
#6 存在多个候选的bean,spring要按优先级决定用哪个,较复杂,不深入。

DefaultListableBeanFactory#findAutowireCandidates

protected Map findAutowireCandidates(
        String beanName, Class requiredType, DependencyDescriptor descriptor) {

    // #1
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this, requiredType, true, descriptor.isEager());    
    Map result = new LinkedHashMap(candidateNames.length);
    // #2
    for (Class autowiringType : this.resolvableDependencies.keySet()) {  
        if (autowiringType.isAssignableFrom(requiredType)) {
            Object autowiringValue = this.resolvableDependencies.get(autowiringType);
            autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
            if (requiredType.isInstance(autowiringValue)) {
                result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                break;
            }
        }
    }
    //#3
    for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {  
            addCandidateEntry(result, candidate, descriptor, requiredType);
        }
    }
    ...
    return result;
}

#1 按类型查找spring上下文中所有的bean
#2 从当前已存在的依赖关系中查找
#3 遍历#1步骤中找到的bean,如果满足Autowire要求,添加到结果
这里检查候选类的类型是否匹配,是否满足@Qualifier的要求,不继续深入,有兴趣的同学自行阅读源码。

如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!


你可能感兴趣的:(SpringBoot源码解析 -- @Value,@Autowired实现原理)