Spring源码分析(三)@Autowired依赖注入源码分析

Spring里面到底有几种依赖注入的方式呢?

1:手动注入

     1)我们在xml文件中定义一个bean的时候,在bean标签下面使用<property name="bird" ref="bird"> 代码中提供set方法,把外部对象注入到bean中的方式就是属于手动注入,因为我们要手动的维护这个属性。

     2)也可以在bean标签下面使用构造函数标签,来指定使用那个构造函数来向bean中注入属性。

2:自动注入

     1)XML里面的自动注入

 autowire可以选择 byType,byName, constructor default,no 

   ----- byType

<bean id="people" class="com.my.ioc.pojo.People"  autowire="byType"/>    
<bean id="bird" class="com.my.ioc.pojo.factorybean.Bird" />

 

 

 

 people里只提供了brid的set方法。

调用getBean(people)就可以得到注入bird的people实例,

 

 这种自动注入,就是在填充people属性的时候获取set方法,发现set方法参数也是个bean的时候,就根据这个参数的类的类型来获取对应的bean,然后调用这个set方法,并把参数的bean实例传递进来赋值给当前的属性,完成自动注入。

---- byName

xml中填写的是byName的时候,这个name不是根据属性名,也不是set方法的参数名,而是set方法名,把set去掉之后剩下的首字母小写之后的内容作为beanName来找bean。

----constructor

 构造方法就涉及到到构造方法的选择,选择的逻辑,分析源码的时候具体记录。

--- default

在xml的最上层有个beans标签,可以在那个里面定义default-autowire="byType"  属性,然后可以在下面定义具体的bean的时候用default值,就按照最上层的那个设置来,如果bean标签没有写autorie属性,也是默认按照default-autowire 指定的来。

-----no

就是不进行自动注入

上篇记录中有看到在填充属性的时候会从从BeanDefinition中获取这个属性值进行判断。 

 

 

2) @Autowired的自动注入

     注解可以用在的地方:方法,属性上,构造方法。如果使用xml来构造容器的话,这个注解默认是不生效的,需要在xml中开启注解: <context:annotation-config></context:annotation-config>

    或者直接使用注解容器。AnnotationConfigApplicationContext

    这个注解其实是上面xml中autowire属性的升级,

    第一个升级的地方就是可以用在属性定义上面,而且注入的过程是先根据byType找到这个类是不是有多个类型,如果找到多个类型再根据属性名byName来找到bean。

    第二个升级的地方就是这个注解可以用在方法上,但是不一定非要用在属性的set方法上,用在任意方法名都可以,只要方法参数是个bean。


 

自动注入的流程:

 

 

 

自动注入使用到的后置处理器:AutowiredAnnotationBeanPostProcessor

 

 

 上面两个标黄的接口和类,上篇实例化过程中提到了。其中的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition 是在实例化后执行的一个后置处理器,而上面的这个实现类AutowiredAnnotationBeanPostProcessor

,就在这个方法逻辑里找到注入点进行解析。在 InstantiationAwareBeanPostProcessor.postProcessProperties 方法中进行实际的注入操作。

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition

 AutowiredAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter重写了里面的postProcessProperties,在这个方法里把上面那个方法找到的注入点进行属性注入。

@Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        // InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
        // 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            //按注入点进行注入
            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;
    }

 

先从怎么找到注入点的方法进行跟进。

 会把一个bean的注入点封装成一个InjectionMetadata( new InjectionMetadata(clazz, elements))elements为所有的注入点。并缓存到this.injectionMetadataCache 一个Map中,key为beanName。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
        // Fall back to class name as cache key, for backwards compatibility with custom callers.
        // 把beanName作为缓存的key
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        // Quick check on the concurrent map first, with minimal locking.
        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) {
                        metadata.clear(pvs);
                    }
                    //寻找当前class的注入点,把所有注入点整合为一个InjectionMetadata
                    metadata = buildAutowiringMetadata(clazz);
                    //放入缓存中
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

 

 buildAutowiringMetadata(clazz)
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        // 判断是不是候选者类,比如说类名是以 java.开头的则不是候选者类 Order的实现类也不是候选者类
        // 但是如果this.autowiredAnnotationTypes 中有以java.开头的注解就返回true了
        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<>();
            // 遍历属性,看是否有@Autowired @Value  @Inject注解
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
                MergedAnnotation<?> ann = findAutowiredAnnotation(field);
                //如果存在上面中的一个
                if (ann != null) {
                    // 如果字段是静态的,则直接进行返回,不进行注入
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
                    // 是否required
                    boolean required = determineRequiredStatus(ann);
                    // 生成一个注入点AutowiredFieldElement
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });
             //遍历所有的方法 看是否有@Autowired @Value  @Inject注解
            ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 这是找字节码中被桥接后的方法 Method bridgedMethod
= BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { //静态方法不能用来注入属性 if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } //方法参数为0 不能用来注入属性 if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); // 是会去找父类 进行递归操作 targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); }

 

这个方法首先会判断当前类是否为候选者。this.autowiredAnnotationTypes 中存着可以被识别为注入点的注解:Inject只有在项目中存在的时候才会添加进来,如果没有报错也不会处理。

 

 候选者的判断条件:

public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
        for (Class<? extends Annotation> annotationType : annotationTypes) {
            if (isCandidateClass(clazz, annotationType)) {
                return true;
            }
        }
        return false;
    }
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
// 注解有java开头的注解就算是候选者,但是一般不会有,除非自己添加
if (annotationName.startsWith("java.")) { return true; }
// 如果clazz是以java.开头或Order的子类,也不算是候选者
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) { return false; } return true; }
    static boolean  hasPlainJavaAnnotationsOnly(Class<?> type) {
        return (type.getName().startsWith("java.") || type == Ordered.class);
    }

 


 

判断它是候选者之后,找到候选者中所有的注入点,分为属性和方法。

1:遍历属性,查看属性上面是否有上面说的三种注解的其中之一,有的话就返回。

@Nullable
    private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
        // 查看当前字段上是否存在@Autowired @Value @Inject注解  存在其中一个则返回,表示可以注入
        MergedAnnotations annotations = MergedAnnotations.from(ao);
        // autowiredAnnotationTypes 是一个LinkHashSet 所以会按照顺序去判断当前字段中是否有Autowired注解,如果有则返回,
        //如果没有则Autowired注解 则判断是否有value注解  再判断是否有Inject注解
        for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
            MergedAnnotation<?> annotation = annotations.get(type);
            if (annotation.isPresent()) {
                return annotation;
            }
        }
        return null;
    }

 

   请注意,上面属性注入点,生成的 InjectionMetadata.InjectedElement的子类 AutowiredFieldElement来存储。

2:找方法中的注入点,这里找的是被桥接后的注入点。关于什么是桥接方法,https://blog.csdn.net/mhmyqn/article/details/47342577

     方法的注入点用  InjectionMetadata.InjectedElement的子类  AutowiredMethodElement  来存储。

 把两中element放入elements 中,

最后调用InjectionMetadata.forElements(elements, clazz); 生成InjectionMetadata返回。

public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
        return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
    }

 


 

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 找到注入点之后。就 在AutowiredAnnotationBeanPostProcessor.postProcessProperties 方法进行注入。

@Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        // InjectionMetadata 中保存了所有被@Autowired注解标注的属性/方法 并封装成一个个的InjectedElement
        // 在postProcessMergedBeanDefinition 方法里已经得到放到缓存中了
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            //按注入点进行注入
            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;
    }

 

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()) {
            //遍历每个能够注入的属性 进行注入
            for (InjectedElement element : elementsToIterate) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Processing injected element of bean '" + beanName + "': " + element);
                }
                // element可能是Method 也可能是Field 会走不同的子类   AutowiredFieldElement  AutowiredMethodElement 都在AutowiredAnnotationBeanPostProcessor 内部
element.inject(target, beanName, pvs); } } }

 


属性注入点注入的的逻辑,AutowiredFieldElement.inject  

@Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                // 当前注入点已经注入过了 有缓存了 则利用缓存this.cachedFieldValue找到对应的bean
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            }
            else {
                //spring在真正查找属性对应的对象之前 会先将该属性的描述封装成一个DependencyDescriptor 里面存了Field
                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 {
//                    根据field去寻找合适的bean
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                }
                synchronized (this) {
                    if (!this.cached) {
                        if (value != null || this.required) {
                            this.cachedFieldValue = desc;
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                if (beanFactory.containsBean(autowiredBeanName) &&
                                        beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                    this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                            desc, autowiredBeanName, field.getType());
                                }
                            }
                        }
                        else {
                            this.cachedFieldValue = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (value != null) {
                // 这里才是真正的赋值操作
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }
        }
    }

 

第一次注入属性,会执行:value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 

找到属性对应的bean。  DefaultListableBeanFactory.resolveDependency,

    //只负责找对象返回出去,赋值时在外面进行的,比如如果时@Value(xxx) 就把xxx返回出去
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        // DependencyDescriptor 表示一个依赖,可以是一个字段,可以是一个属性字段,可能是一个构造方法参数,可能是一个set方法参数
        //根据descriptor去BeanFactory中找到bean
        descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
        //如果依赖类型是Optional
        if (Optional.class == descriptor.getDependencyType()) {
// 注入的时候就是 Optional<OrderService> orderservice; 这个方法内部调用的也是doResolveDependency方法只是把返回结果封装成了Optional. orderservice.get()才能得到里面的实例
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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { //在使用@Autowired 注解时 也可以使用@Lazy注解,到时候注入的会是一个代理对象 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { //通过解析descriptor找到bean对象 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }

 

 先看主要获取实例的方法: doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);  自动注入的逻辑最主要逻辑就是找到注入的对象,这个方法就是处理这个逻辑的:

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

        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
        try {
            //1: 如果DepenDencyDescriptor是一个 ShortcutDependencyDescriptor
            // 那么 会直接理解成beanName从beanfactoryz中拿到一个bean
            //在利用@autowired注解来进行依赖注入时会利用shortcutDependencyDescriptor来进行依赖注入的缓存
            //表示当解析完某个依赖信息后  会把依赖的bean的beanName缓存起来
            Object shortcut = descriptor.resolveShortcut(this);
            if (shortcut != null) {
                return shortcut;
            }
            //获取descriptor具体的类型  某个Filed的类型 或者某个方法参数的类型
            Class<?> type = descriptor.getDependencyType();
            // 2:如果descriptor上有@Value注解  获取@Value注解中所配置的值 这个resolver是 QualifierAnnotationAutowireCandidateResolver
            //  AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE; 这是默认的resolver,它可以判断某个bean是不是一个自动注入的候选bean
            //  比如: xml中定义的bean可以写个 autowire-candidate="false" 把bean排除 不是自动装配的bean
            Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
            if (value != null) {
                if (value instanceof String) {
                    // 先进行占位符的填充,解析$符号 $(xxx)   spring会从环境变量中获取xxx对应的value进行填充
                    String strVal = resolveEmbeddedValue((String) value);
                    BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                            getMergedBeanDefinition(beanName) : null);
                    // 解析Spring EL表达式 解析# 符号 (可以进行运算  可以写某个bean的名字)
                    value = evaluateBeanDefinitionString(strVal, bd);
                }
                TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
                try {
                    // 使用类型转换器,转换@Value得到的字符串到type类型
                    return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
                }
                catch (UnsupportedOperationException ex) {
                    // A custom TypeConverter which does not support TypeDescriptor resolution...
                    return (descriptor.getField() != null ?
                            converter.convertIfNecessary(value, type, descriptor.getField()) :
                            converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
                }
            }
            // 没有使用@Value注解
            //3:要注入的类型是不是一个Map,collection
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                return multipleBeans;
            }

            //4: 表示会根据type去找bean,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象,因为该方法只负责根据类型找到对应的bean,
            // 如果该bean 还没有实例化,那么就返回bean对应的class对象
            //  该方法也不负责实例化,只返回该bean对应的Class对象,表示这个Bean也是结果之一)
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

            // 如果根据类型没有找到bean 如果时必须的则抛出异常  如果不是必须的则直接返回 null
            if (matchingBeans.isEmpty()) {
                if (isRequired(descriptor)) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                return null;
            }

            String autowiredBeanName;
            Object instanceCandidate;
            //如果找到多个,根据其它参数确定一个返回  {@code @Primary} and {@code @Priority} (in that order)
            if (matchingBeans.size() > 1) {

                autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                        return descriptor.resolveNotUnique(descriptor.getResolvableType(), 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);
            }
            //如果返回的是Class类型就从beanFactory中getBean
            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);
        }
    }

 

第一步先判断 descriptor是不是具体的类型,ShortcutDependencyDescriptor 说明已经处理过了,直接从工厂中获取。

第二步,先判断的注解是@Value, 如果存在这个注解就解析,如果解析出来的值能找到类型转换器进行转换,就把结果返回出去。

第三步,判断是不是map和集合的类型,如果是的话就返回相对应的类型实例。

第四步,如果上面都没匹配到结果,就根据类型找到这个的类型的相关bean,封装成一个map返回,Map的key为beanName,Map 的value为对象 (注意可能是bean对象 也可能是某个bean的class对象)

找到候选者bean的逻辑: findAutowireCandidates

// 根据requiredType 找到自动匹配的候选者bean
    protected Map<String, Object> findAutowireCandidates(
            @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

        // Ancestors 是祖先的意思,这个方法是根据requiredType去当前以及祖先的beanFactory中找这个类型的beanName
        String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this, requiredType, true, descriptor.isEager());
        Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);

 // 先从 resolvableDependencies 中
        for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
            Class<?> autowiringType = classObjectEntry.getKey();
            // requiredType 是autowiringType的子类
            //requiredType 类是不是继承或实现了autowiringType,autowiringType为父类或接口,子类对象可以赋值给父类属性
            if (autowiringType.isAssignableFrom(requiredType)) {
                // 是resolvableDependencies中子类所存的对象
                Object autowiringValue = classObjectEntry.getValue();
                autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
                if (requiredType.isInstance(autowiringValue)) {
                    //把 resolvableDependencies中保存的对象作为当前属性的一个候选者
                    result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                    break;
                }
            }
        }
        // 对候选者bean进行过滤,首先候选者不是自己,然后候选者是支持自动注入给其它beand的
        for (String candidate : candidateNames) {
            // isAutowireCandidate方法中会去判断候选者是否和descriptor匹配 并不是所有bean都是可以进行注入的
// 如果isAutowireCandidate返回的false,也是不会把它作为候选者beanName
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty()) { boolean multiple = 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) && (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty() && !multiple) { // 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; }

 

 返回候选者的map之后,如果这个map为空,则直接返回方法结束,如果map中只有一个候选者,那就是需要注入的值就是这个map的value值了。

但是如果Map中有多个候选者,就要从这些候选者中筛选出一个唯一的一个候选者返回。

筛选唯一beanName的方法是:determineAutowireCandidate 。就是判断这个候选者的bean上是否有@Primary  @Priority(注意是有顺序的) ,如果都没有就  根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName 相等就返回

@Nullable
    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        // 取@Primary 的bean
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }
        // 取优先级最高的bean,通过@Priority来定义优先级 数字越小  优先级越高
        String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        }
        // Fallback
        // 如果根据上面的 @Primary  @Priorityd都没找到,就根据属性名/方法参数名从map中获取一个候选beanName
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateName = entry.getKey();
            Object beanInstance = entry.getValue();
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    // 根据属性名/方法参数名确定,找到的candidateName 和当前descriptor.getDependencyName  相等就返回
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }

 

 


 

根据 找到的autowiredBeanName 从map获取到 instanceCandidate,上面提到过这个实例候选者不一定就是需要注入的对象,可能是Class对象,如果是Class对象,就从beanFactory中获取对象的bean对象返回。

 


 

 在上面找候选者bean的方法 findAutowireCandidates 是一段很重要的逻辑,里面有怎么根据type找到对应的所有的beanName(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager())),  以及怎么判断找到的这些bean是不是可以作为候选者bean(方法isAutowireCandidate)。

 根据类型找到所有的beanName, 就是遍历所有的beanDefinition看对应的类型是不是和type匹配,当然这个过程设计到很多逻辑,因为beanDefinition类型太多了,这里不展开讲了。

根据类型找到的这些beanName还不能直接返回,还要判断是不是可以作为候选者beanName, 这里我们上面提到过,有一个 autowire-candidate 属性如果是false,表示这个bean不能作为候选者让其它bean注入。

 

 isAutowireCandidate 方法我们点进去看:

1: 2:

3: 在第三个方法中,才调用真正判断是否为候选者。实现类是 QualifierAnnotationAutowireCandidateResolver。


 

1:QualifierAnnotationAutowireCandidateResolver# isAutowireCandidate

首先调用父类的 isAutowireCandidate 方法,如果父类匹配的上再进行自己逻辑的判断,如果父类都不过,则直接false。

 

 2:父类1  GenericTypeAwareAutowireCandidateResolver# isAutowireCandidate

 

 3:父类2   SimpleAutowireCandidateResolver# isAutowireCandidate

到这里才是判断 autowire-candidate 属性是否为true的,也就是首先判断这个属性是否为true,如果为false,则这个bean直接认为不是候选者。但是为true了,这个bean也不一定是候选者,还有其它判断。

 

 

 回到父类2中。如果父类3返回true了,执行自己的判断逻辑: checkGenericTypeMatch(bdHolder, descriptor);   这是泛型匹配,也就是注入点可以是泛型。举个例子:

public class Father<T> {
   @Autowired
    private T t;
    public T getT() {
        return t;
    }
}
@Service
public class Son extends Father<People> {
}
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        System.out.println("======================");
         Son son=(Son)applicationContext.getBean("son");
        System.out.println(son.getT());

 

 上面的结果是People可以正常被注入到t上面的。

 

注意如果注入点是个泛型,在上面 findAutowireCandidates  把所有的beanName都找出来了,挨个遍历找到和泛型类型匹配的类型bean。

 

 

如果没有泛型,这个父类2就返回true了。

走到QualifierAnnotationAutowireCandidateResolver 中的逻辑。这个类自己的逻辑就是匹配@Qualifier注解的。关于这个的作用参考:https://www.cnblogs.com/krock/p/14820404.html  


 

总结:

对于@Autowired ,@Value,@Inject注解标识的注入点,注入的流程:

1:根据注解找到注入点

2:根据注入点进行注入,首先判断的是@Value,如果有@Value注解,就把注解中配置的属性值解析进行注入,这里会有类型转换。

3: 如果没有@Value注解,就先byType,再byName的方式找到唯一的bean进行注入。

4:byType会找到很多类型的beanName出来,先byType到byName中间会经过6步筛选:

1)判断是否为候选者isAutowireCandidate是否为true

2)如果是候选者,判断是否注入点的类型是泛型,如果是泛型执行GenericTypeAwareAutowireCandidateResolver中的逻辑

3)判断注入点是否使用了@Qualifier 注解,如果使用了执行QualifierAnnotationAutowireCandidateResolver 的匹配逻辑

经过上面的三步,得到一个Map<beanName, 对象(bean实例或者bean相应的Class对象)>,这个Map中数据可能是多个

 4)继续筛选Map中的beanName,判断,beanName对应的bean上面是否有 @Primary注解,如果有的话,直接用这个beanName对应的value值。

5) 如果没有@Primary,判断bean上面是否有@Priority(1/2/3) 优先级,值越小优先级越高。

6)如果上面都没能唯一确认一个bean, 就根据注入点的属性名或方法参数名从Map看是否有对应的key,如果找到了就返回。

 

 

 

 

 
posted @ 2021-05-29 00:41  蒙恬括  阅读(731)  评论(0编辑  收藏  举报