• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

Spring注解@Autowired源码分析

Spring winrains 来源:大王叫下 12个月前 (10-13) 44次浏览

AutowiredAnnotationBeanPostProcessor是Spring的后置处理器,专门处理@Autowired和@Value注解。

一、触发方式

  • Spring容器在每个Bean实例化之后,调用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,查找该Bean是否有@Autowired注解。
  • Spring在每个Bean实例化的时候,调用populateBean进行属性注入的时候,即调用postProcessPropertyValues方法,查找该Bean是否有@Autowired注解。

二、构造函数

public AutowiredAnnotationBeanPostProcessor() {
    //后置处理器将处理@Autowire注解
    this.autowiredAnnotationTypes.add(Autowired.class);
    //后置处理器将处理@Value注解
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        //后置处理器将处理javax.inject.Inject JSR-330注解
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

三、注入的方法

// 处理类中的属性,属性注入
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
        String beanName) throws BeanCreationException {
//获取指定类中autowire相关注解的元信息
<1>    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 对Bean的属性进行自动注入
<2>        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;
}

该方法就是在属性注入populateBean中调用的pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);的具体实现之一。
<1> 处的代码是从该bean中获取对应的注解信息,在AutowiredAnnotationBeanPostProcessor这里就是寻找有加@Value、@Autowired注解的字段,然后把相关信息封装在InjectionMetadata。代码如下:

// 获取给定类的autowire相关注解元信息
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom
    // callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    // 首先从容器中查找是否有给定类的autowire相关注解元信息
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    // 解析给定类autowire相关注解元信息
                    metadata.clear(pvs);
                }
                // 解析给定类autowire相关注解元信息
                metadata = buildAutowiringMetadata(clazz);
                // 将得到的给定类autowire相关注解元信息存储在容器缓存中
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

下面来看buildAutowiringMetadata的详细代码:

// 解析给定类autowire相关注解元信息
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    // 创建一个存放注解元信息的集合
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
    Class<?> targetClass = clazz;
    // 递归遍历当前类及其所有基类,解析全部注解元信息
    do {
        // 创建一个存储当前正在处理类注解元信息的集合
        final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
        // 利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // 获取给定字段上的注解
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
                // 如果给定字段是静态的(static),则直接遍历下一个字段
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                // 判断注解的required属性值是否有效
                boolean required = determineRequiredStatus(ann);
                // 将当前字段元信息封装,添加在返回的集合中
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });
        // 利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            // 获取给定方法上的所有注解
            AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                // 如果方法是静态的,则直接遍历下一个方法
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                // 如果方法的参数列表为空
                if (method.getParameterCount() == 0) {
                    if (logger.isWarnEnabled()) {
                        logger.warn(
                                "Autowired annotation should only be used on methods with parameters: " + method);
                    }
                }
                // 判断注解的required属性值是否有效
                boolean required = determineRequiredStatus(ann);
                // 获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                // 将方法元信息封装添加到返回的元信息集合中
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });
        // 将当前类的注解元信息存放到注解元信息集合中
        elements.addAll(0, currElements);
        // 获取给定类的父类
        targetClass = targetClass.getSuperclass();
    }
    // 如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
    while (targetClass != null && targetClass != Object.class);
    return new InjectionMetadata(clazz, elements);
}

这段代码的注释很清晰了,到这一步就拿到了指定类中autowire相关注解的元信息。
ps:这里可以看到@Autowired注解是不支持static修饰的
我们接着看postProcessPropertyValues方法的<2>处具体的注入逻辑:

// InjectionMetadata.java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    // 要注入的字段集合
    Collection<InjectedElement> elementsToIterate = (checkedElements != null ? 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);
            }
            element.inject(target, beanName, pvs);
        }
    }
}

这里还不是真正注入的方法,我们继续追踪element.inject(target, beanName, pvs);

// InjectionMetadata.java
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
        throws Throwable {
    if (this.isField) {
        Field field = (Field) this.member;
        ReflectionUtils.makeAccessible(field);
        field.set(target, getResourceToInject(target, requestingBeanName));
    } else {
        if (checkPropertySkipping(pvs)) {
            return;
        }
        try {
            Method method = (Method) this.member;
            ReflectionUtils.makeAccessible(method);
            method.invoke(target, getResourceToInject(target, requestingBeanName));
        } catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

这是element.inject()的原始方法,它还有两个子类自己实现的方法,如图:

从方法名称可以看出,一个是对字段进行注入,一个是对方法进行注入。并且这两个方法都是AutowiredAnnotationBeanPostProcessor具体的实现。

3.1、字段注入

我们先来看下对字段的注入:

// AutowiredAnnotationBeanPostProcessor.java
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // 获取要注入的字段
    Field field = (Field) this.member;
    Object value;
    // 如果字段的值有缓存
    if (this.cached) {
        // 从缓存中获取字段值value
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    // 没有缓存
    else {
        // 创建一个字段依赖描述符
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        // 获取容器中的类型转换器
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // 核心!获取注入的值
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        // 线程同步,确保容器中数据一致性
        synchronized (this) {
            // 如果字段的值没有缓存
            if (!this.cached) {
                // 字段值不为null,并且required属性为true
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    // 为指定Bean注册依赖Bean
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        // 如果容器中有指定名称的Bean对象
                        if (beanFactory.containsBean(autowiredBeanName)) {
                            // 依赖对象类型和字段类型匹配,默认按类型注入
                            if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                // 创建一个依赖对象的引用,同时缓存
                                this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName,
                                        field.getType());
                            }
                        }
                    }
                }
                // 如果获取的依赖关系为null,且获取required属性为false
                else {
                    // 将字段值的缓存设置为null
                    this.cachedFieldValue = null;
                }
                // 容器已经对当前字段的值缓存
                this.cached = true;
            }
        }
    }
    // 如果字段值不为null
    if (value != null) {
        // 显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
        ReflectionUtils.makeAccessible(field);
        // 为字段赋值
        field.set(bean, value);
    }
}

这段代码很好理解,从注解@Value/@Autowired中获取要注入的值,之后利用反射set到字段中。
重点就是怎么从注解中获取要注入的值,我们来看核心代码value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

// DefaultListableBeanFactory.java
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
    } else if (ObjectFactory.class == descriptor.getDependencyType()
            || ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    } else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
    } else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor,
                requestingBeanName);
        if (result == null) {
            // 真正获取值的代码
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

进行跟踪:

// DefaultListableBeanFactory.java
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        //注入点
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        // 针对给定的工厂给定一个快捷实现的方式,例如考虑一些预先解析的信息
        // 在进入所有bean的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式。
        // 子类可以覆盖此方法
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }
        //获取字段属性的类型
        Class<?> type = descriptor.getDependencyType();
        //拿到@Value里的值
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }
        //如果标识@Autowired注解的属性是复合类型,如Array,Collection,Map,
        // 从这个方法获取@Autowired里的值
<1>     Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        //如果标识@Autowired注解的属性是非复合类型,
        // 从这个方法获取@Autowired里的值
<2>     Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        //如果没有符合该类型的Bean
        if (matchingBeans.isEmpty()) {
            // 没有找到,检验 @autowire  的 require 是否为 true
            if (isRequired(descriptor)) {
                //抛出异常
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }
        String autowiredBeanName;
        Object instanceCandidate;
        //如果符合该类型的Bean有多个
        if (matchingBeans.size() > 1) {
            //挑选出最优解
<3>         autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    //抛出异常
                    return descriptor.resolveNotUnique(type, matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

这段代码看着很长,但其实很容易理解。大致流程就是:
根据字段类型从IOC容器中获取符合的Bean,如果有多个,则挑选出最优的那一个。
下面来看下具体逻辑。

3.1.1、<1>处:@Autowired注入集合数组,如Map.List

先来看下@Autowired注入集合数组的逻辑:

// DefaultListableBeanFactory.java
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    Class<?> type = descriptor.getDependencyType();
    // 如果@Autowired标识的是数组类型的属性
    if (type.isArray()) {
        // 获取数组的内容类型
        Class<?> componentType = type.getComponentType();
        ResolvableType resolvableType = descriptor.getResolvableType();
        Class<?> resolvedArrayType = resolvableType.resolve();
        if (resolvedArrayType != null && resolvedArrayType != type) {
            type = resolvedArrayType;
            componentType = resolvableType.getComponentType().resolve();
        }
        if (componentType == null) {
            return null;
        }
        // 通过类型去IOC容器内择取符合的Bean都是使用这个方法
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
                new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        // 将得到的Bean的候选者们转换为属性类型,如从set转换为Array,List等
        Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        if (getDependencyComparator() != null && result instanceof Object[]) {
            Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
        }
        return result;
    } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        // 获取Collection的泛型
        Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
        if (elementType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
                new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        if (getDependencyComparator() != null && result instanceof List) {
            Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));
        }
        return result;
    } else if (Map.class == type) {
        ResolvableType mapType = descriptor.getResolvableType().asMap();
        Class<?> keyType = mapType.resolveGeneric(0);
        if (String.class != keyType) {
            return null;
        }
        Class<?> valueType = mapType.resolveGeneric(1);
        if (valueType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
                new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        return matchingBeans;
    } else {
        return null;
    }
}

3.1.2、<2>处:@Autowired注入非集合数组,即普通的类如Service

// DefaultListableBeanFactory.java
protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType,
        DependencyDescriptor descriptor) {
    // 从IOC容器中获取所有的符合类型的BeanName,存入候选数组
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true,
            descriptor.isEager());
    Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    // 首先从容器自身注册的依赖解析来匹配,Spring容器自身注册了很多Bean的依赖,
    // 当使用者想要注入指定类型的Bean时,会优先从已注册的依赖内寻找匹配
    for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
        if (autowiringType.isAssignableFrom(requiredType)) {
            Object autowiringValue = this.resolvableDependencies.get(autowiringType);
            autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
            // 如果注册的依赖Bean类型是指定类型的实例或是其父类,接口,则将其作为候选者,注册依赖的类型不会重复
            if (requiredType.isInstance(autowiringValue)) {
                result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                break;
            }
        }
    }
    // 遍历候选数组
    for (String candidate : candidateNames) {
        // 候选Bean不是自引用(即要注入的类不能是类本身,会触发无限递归注入)
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
        }
    }
    if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
        // Consider fallback matches if the first pass failed to find anything...
        DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
        for (String candidate : candidateNames) {
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }
        if (result.isEmpty()) {
            // Consider self references as a final pass...
            // but in the case of a dependency collection, not the very same bean itself.
            for (String candidate : candidateNames) {
                if (isSelfReference(beanName, candidate)
                        && (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate))
                        && isAutowireCandidate(candidate, fallbackDescriptor)) {
                    addCandidateEntry(result, candidate, descriptor, requiredType);
                }
            }
        }
    }
    return result;
}

这段代码注释已经写的很清楚了,我们来继续看下addCandidateEntry方法,该方法是把Bean实例放入到候选者集合中

// DefaultListableBeanFactory.java
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
        DependencyDescriptor descriptor, Class<?> requiredType) {
    // 当@Autowired标识的是容器类型的属性,生成的依赖描述类型是MultiElementDescriptor ,
    // 因此所有的候选者均是合格的,所以会当场实例化他们。而如果属性的类型非容器,那么可能是多个候选者中挑一个,
    // 此时实例化他们所有就不合适了,最终会把合格的那个实例化,如果没有合格的则不实例化,
    // 提前实例化对Bean的很多方面有影响,比如AOP,EarlyReference等 */
    if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
        Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
        candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
    } else {
        candidates.put(candidateName, getType(candidateName));
    }
}

这里会调用doGetBean()方法进行实例化Bean

3.1.3、<3>处:多个候选者中挑选出最优解

如果根据类型从IOC容器中获得的Bean有多个,那么就需要调用determineAutowireCandidate(matchingBeans, descriptor)方法,去挑选出最优解。
代码:

// DefaultListableBeanFactory.java
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    Class<?> requiredType = descriptor.getDependencyType();
    // 根据@Primary注解来择取最优解
    String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    }
    // 根据@Order,@PriorityOrder,及实现Order接口的序号来择取最优解
    String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
    if (priorityCandidate != null) {
        return priorityCandidate;
    }
    // Fallback
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateName = entry.getKey();
        Object beanInstance = entry.getValue();
        // 如果通过以上两步都不能选择出最优解,则使用最基本的策略
        // 首先如果这个类型已经由Spring注册过依赖关系对,则直接使用注册的对象,
        // 候选者集合是LinkedHashMap,有序Map集合,容器注册的依赖对象位于LinkedHashMap的起始位置
        // 如果没有注册过此类型的依赖关系,则根据属性的名称来匹配,、
        // 如果属性名称和某个候选者的Bean名称或别名一致,那么直接将此Bean作为最优解
        if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance))
                || matchesBeanName(candidateName, descriptor.getDependencyName())) {
            return candidateName;
        }
    }
    return null;
}

这部分逻辑比较简单,总结就是3个步骤:

  • 根据@Primary注解来择取最优解
  • 根据@Order,@PriorityOrder,及实现Order接口的序号来择取最优解
  • 根据Spring默认规则

我们逐一分析这几个步骤,先看第一个:
根据@Primary注解来择取最优解

// DefaultListableBeanFactory.java
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String primaryBeanName = null;
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        // 候选者可以是父容器内的标识了@Primary的Bean,也可以是当前容器的。SpringMVC容器将Spring容器作为父容器
        if (isPrimary(candidateBeanName, beanInstance)) {
            if (primaryBeanName != null) {
                boolean candidateLocal = containsBeanDefinition(candidateBeanName);
                boolean primaryLocal = containsBeanDefinition(primaryBeanName);
                // 此处确保同一个容器中同一个类型的多个Bean最多只有一个Bean标识了@Primary
                if (candidateLocal && primaryLocal) {
                    throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                            "more than one 'primary' bean found among candidates: " + candidates.keySet());
                }
                // 如果上一个@Primary的Bean是父容器的,则用当前容器的候选者覆盖之前的@Primary的Bean
                else if (candidateLocal) {
                    primaryBeanName = candidateBeanName;
                }
            } else {
                primaryBeanName = candidateBeanName;
            }
        }
    }
    return primaryBeanName;
}

接着看第二个:
根据@Order,@PriorityOrder

// DefaultListableBeanFactory.java
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String highestPriorityBeanName = null;
    Integer highestPriority = null;
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        Integer candidatePriority = getPriority(beanInstance);
        if (candidatePriority != null) {
            // 不能同时存在两个最高优先级的序号
            if (highestPriorityBeanName != null) {
                if (candidatePriority.equals(highestPriority)) {
                    throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                            "Multiple beans found with the same priority ('" + highestPriority
                                    + "') among candidates: " + candidates.keySet());
                }
                // 使用优先级序号最小的Bean作为最优解
                else if (candidatePriority < highestPriority) {
                    highestPriorityBeanName = candidateBeanName;
                    highestPriority = candidatePriority;
                }
            } else {
                highestPriorityBeanName = candidateBeanName;
                highestPriority = candidatePriority;
            }
        }
    }
    return highestPriorityBeanName;
}

小结
到这里,@Autowired字段注入的源码就分析完毕了。
接下来我们看下方法注入:

3.2、方法注入

// DefaultListableBeanFactory.java
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // 如果属性被显式设置为skip,则不进行注入
    if (checkPropertySkipping(pvs)) {
        return;
    }
    // 获取注入元素对象
    Method method = (Method) this.member;
    Object[] arguments;
    // 如果容器对当前方法缓存
    if (this.cached) {
        // Shortcut for avoiding synchronization...
        // 获取缓存中指定Bean名称的方法参数
        arguments = resolveCachedArguments(beanName);
    }
    // 如果没有缓存
    else {
        // 获取方法的参数列表
        Class<?>[] paramTypes = method.getParameterTypes();
        // 创建一个存放方法参数的数组
        arguments = new Object[paramTypes.length];
        DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
        Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
        Assert.state(beanFactory != null, "No BeanFactory available");
        // 获取容器的类型转换器
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        for (int i = 0; i < arguments.length; i++) {
            // 创建方法参数对象
            MethodParameter methodParam = new MethodParameter(method, i);
            DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
            currDesc.setContainingClass(bean.getClass());
            // 解析方法的输入参数,为方法参数创建依赖描述符
            descriptors[i] = currDesc;
            try {
                Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
                if (arg == null && !this.required) {
                    arguments = null;
                    break;
                }
                // 根据容器中Bean定义解析依赖关系,获取方法参数依赖对象
                arguments[i] = arg;
            } catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
            }
        }
        // 线程同步,以确保容器中数据一致性
        synchronized (this) {
            // 如果当前方法没有被容器缓存
            if (!this.cached) {
                // 如果方法的参数列表不为空
                if (arguments != null) {
                    // 为容器中缓存方法参数的对象赋值
                    Object[] cachedMethodArguments = new Object[paramTypes.length];
                    for (int i = 0; i < arguments.length; i++) {
                        cachedMethodArguments[i] = descriptors[i];
                    }
                    // 为指定Bean注册依赖Bean
                    registerDependentBeans(beanName, autowiredBeans);
                    // 如果依赖对象集合大小等于方法参数个数
                    if (autowiredBeans.size() == paramTypes.length) {
                        Iterator<String> it = autowiredBeans.iterator();
                        // 为方法参数设置依赖对象
                        for (int i = 0; i < paramTypes.length; i++) {
                            String autowiredBeanName = it.next();
                            // 如果容器中存在指定名称的Bean对象
                            if (beanFactory.containsBean(autowiredBeanName)) {
                                // 如果参数类型和依赖对象类型匹配
                                if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                                    // 创建一个依赖对象的引用,复制给方法相应的参
                                    cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i],
                                            autowiredBeanName, paramTypes[i]);
                                }
                            }
                        }
                    }
                    this.cachedMethodArguments = cachedMethodArguments;
                }
                // 如果方法参数列表为null,则设置容器对该方法参数的缓存为null
                else {
                    this.cachedMethodArguments = null;
                }
                // 设置容器已经对该方法缓存
                this.cached = true;
            }
        }
    }
    // 如果方法参数依赖对象不为null
    if (arguments != null) {
        try {
            // 使用JDK的反射机制,显式设置方法的访问控制权限为允许访问
            ReflectionUtils.makeAccessible(method);
            // 调用Bean的指定方法
            method.invoke(bean, arguments);
        } catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

总结

@Autowired注解的原理用一句话讲明:
就是先从IOC容器中根据类型找到所有符合的Bean,然后再根据@Primary、@Order、@PriorityOrder或Spring默认规则挑选出最符合的Bean,利用反射注入到字段中。

作者:大王叫下

来源:https://juejin.im/post/5d9edf18f265da5b7a7543e9


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (1)