6、Spring源码-依赖注入(下)

烟雨 4年前 (2021-07-23) 阅读数 347 #Spring源码
文章标签 Spring
前面依赖注入(上),分析了Spring中的自动注入(byName,byType)和@Autowired注解的工作原理以及源码。
其中在inject()方法中有一个beanFactory.resolveDependency()方法,大致是:根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

//resolveDependency方法定义
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
}

该方法传入一个依赖描述(DependencyDescriptor)descriptor,该方法会根据该依赖描述从BeanFactory中找出对应的唯一的一个Bean对象,然后返回。

比如注入的是字段类型的,从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) {
        //根据Bean名称解析缓存中的字段值
        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 {
            //根据容器中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) {
                //获取到了当前对象的依赖对象,并且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);
        //为Bean对象的字段设置值
        field.set(bean, value);
    }
}

第一次解析是没有缓存的,会进入resolvedCachedArgument()方法。

@Nullable
private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
    // 判断是否是一个依赖描述器
    if (cachedArgument instanceof DependencyDescriptor) {
        DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
        Assert.state(beanFactory != null, "No BeanFactory available");
        return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
    }
    else {
        return cachedArgument;
    }
}

DefaultListableBeanFactory.resolveDependency()方法

@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
	//用来获取参数名字
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    //判断是否进行Optional包装处理
    if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
    }
    //判断是否进行ObjectFactory或ObjectProvider的延迟加载的处理
    else if (ObjectFactory.class == descriptor.getDependencyType() ||
             ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
    //Jsr330规范相关处理
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
    }
    else {
        //理依赖注入逻辑
		//在属性/set方法上使用了@Lazy注解,那么构造一个代理对象进行返回,真正使用代理对象的时候才进行Bean筛选
        //ContextAnnotationAutowireCandidateResolver.getLazyResolutionProxyIfNecessary()方法会调用
		//isLazy()和buildLazyResolutionProxy()
		//其中buildLazyResolutionProxy()会调用到doResolveDependency()获取注入的Bean
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
        //如果没有代理对象
        if (result == null) {
            //descriptor表示某个方法的参数/set方法
			//requestingBeanName表示正在进行依赖注入的BeanName
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
	}

doResolveDependency()方法

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

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        //如果当前descriptor之前做过依赖注入,直接取出返回。相当于一个缓存
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }
        //获取类型,有可能是字段类型,有可能是方法类型
        Class<?> type = descriptor.getDependencyType();
        //处理@Value,获取@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);
                //解析Spring表达式(#{})
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            //将value转化为descriptor所对应的类型
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }
        //如果descriptor所对应的是:数组/List/Map这些。就将descriptor对应的类型所匹配的Bean放入multipleBeans,返回。
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        //找到所有Bean,key是BeanName,value有可能是Bean对象,也有可能是beanClass
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            //根据类型找到多个,做进一步的筛选,@Primary --> 优先级(数字越小的优先级越高) --> name
            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();
        }

        //记录匹配过的BeanName
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        //有可能筛选出来的是某个Bean的类型,此处就进行实例化,调用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);
    }
}

以上大致是DefaultListableBeanFactoryresolveDependency()方法的实现,具体流程图如图:

image.png接下来看Spring是如何寻找Bean的,关键代码在doResolveDependency()中的findAutowireCandidates()方法中,基于一个类型type找Bean。

//找到所有Bean,key是BeanName,value有可能是Bean对象,也有可能是beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

如何去找所匹配的BeanNames

findAutowireCandidates()源码,先重点看Spring是如何去找所匹配的BeanNames的,下面代码6行
protected Map<String, Object> findAutowireCandidates(
    @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    //从BeanFactory中找出和requiredType所匹配的beanName
    //这些beanName所对应的Bean不一定经过实例化过程
    //只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        this, requiredType, true, descriptor.isEager());
    Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    //根据类型resolvableDependencies中匹配的bean
    //resolvableDependencies中存放的是类型:Bean对象
    //比如BeanFactory.class:BeanFactory对象,在Spring启动时会对resolvableDependencies这个缓存放入数据,存储的是一个类型所对应的Bean对象
    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;
            }
        }
    }
    //这里如果匹配到了2个bean,其中一个是自己,不会先注入自己,优先注入非自己的那个bean
    for (String candidate : candidateNames) {
        //如果不是自己,则判断该candidate到底能不能用来进行自动注入
        //isAutowireCandidate()判断是否可以依赖注入,处理的是注解@Bean的参数autowireCandidate,默认值为true
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            //向result放入所匹配的候选Bean
            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) {
            //isAutowireCandidate()判断是否可以依赖注入,处理的是注解@Bean的参数autowireCandidate,默认值为true
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
                //向result放入所匹配的候选Bean
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }
        //匹配的是自己,把自己添加到result中,并返回
        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)) {
                    //向result放入所匹配的候选Bean
                    addCandidateEntry(result, candidate, descriptor, requiredType);
                }
            }
        }
    }
    return result;
}
BeanFactoryUtils.beanNamesForTypeIncludingAncestors()方法,它根据一个type去寻找所对应的BeanNames。
这些beanNames所对应的Bean不一定经过实例化过程,只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化。
public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    Assert.notNull(lbf, "ListableBeanFactory must not be null");
    //从本地容器中找
    String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
    //再从父容器找并放入result
    if (lbf instanceof HierarchicalBeanFactory) {
        HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
        if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
            String[] parentResult = beanNamesForTypeIncludingAncestors(
                (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
            List<String> resultList = new ArrayList<>();
            resultList.addAll(Arrays.asList(result));
            for (String beanName : parentResult) {
                if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
                    resultList.add(beanName);
                }
            }
            result = StringUtils.toStringArray(resultList);
        }
    }
    return result;
}

通getBeanNamesForType()方法,具体使用的实现类为DefaultListableBeanFactory,根据一个type寻找匹配的BeanName。

@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    //如果没有冻结,就根据类型去BeanFactory找,如果冻结了,可能就跳过这个if然后去缓存中去拿了
    if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
        return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
    }
    //把当前类型所匹配的beanName缓存起来
    //includeNonSingletons参数的意思,获取时是否包不包括非单例Bean.
    //true:查询所有bean缓存(allBeanNamesByType) false:只查询单例Bean缓存(singletonBeanNamesByType)
    Map<Class<?>, String[]> cache =
        (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
    String[] resolvedBeanNames = cache.get(type);
    if (resolvedBeanNames != null) {
        return resolvedBeanNames;
    }
    //缓存如果为命中
    resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
    if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
        cache.put(type, resolvedBeanNames);
    }
    return resolvedBeanNames;
}

调用另一个重载方法doGetBeanNamesForType()

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<>();

    // Check all bean definitions.
    //遍历所有的BeanDefinitions
    for (String beanName : this.beanDefinitionNames) {
        // Only consider bean as eligible if the bean name
        // is not defined as alias for some other bean.
        if (!isAlias(beanName)) {
            try {
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // Only check bean definition if it is complete.
                //判断mbd允不允许获取对应类型
                //首先mdb不能是抽象的,然后allowEagerInit为true,则直接去推测mdb的类型,并进行匹配
                //如果allowEagerInit为false,那就继续判断,如果mdb还没有加载类并且是懒加载的并且不允许提前加载类,那mbd不能用来进行匹配(因为不允许提前加载类,只能在此mdb自己去创建bean对象时才能去创建类)
                //如果allowEagerInit为false,并且mbd已经加载类了,或者是非懒加载的,或者允许提前加载类,并且不用必须提前初始化才能获取类型,那么就可以去进行匹配了
                //这个条件有点复杂,但是如果只考虑大部分流程,则可以忽略这个判断,因为allowEagerInit传进来的基本上都是true
                if (!mbd.isAbstract() && (allowEagerInit ||
                                          ((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
                                          !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                    // In case of FactoryBean, match object created by FactoryBean.
                    //是否是一个FactoryBean
                    boolean isFactoryBean = isFactoryBean(beanName, mbd);
                    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();

                    //在筛选Bean时,如果仅仅只包括单例,但是beanName对应的又不是单例,则忽略
                    boolean matchFound =
                        (allowEagerInit || !isFactoryBean ||
                         (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
                        (includeNonSingletons ||
                         (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
                        isTypeMatch(beanName, type);
                    //当前BeanDefinition不是FactoryBean,也就是普通Bean
                    if (!matchFound && isFactoryBean) {
                        // In case of FactoryBean, try to match FactoryBean instance itself next.
                        beanName = FACTORY_BEAN_PREFIX + beanName;
                        matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
                    }
                    if (matchFound) {
                        result.add(beanName);
                    }
                }
            }
            catch (CannotLoadBeanClassException ex) {
                if (allowEagerInit) {
                    throw ex;
                }
                // Probably contains a placeholder: let's ignore it for type matching purposes.
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
                }
                onSuppressedException(ex);
            }
            catch (BeanDefinitionStoreException ex) {
                if (allowEagerInit) {
                    throw ex;
                }
                // Probably contains a placeholder: let's ignore it for type matching purposes.
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
                }
                onSuppressedException(ex);
            }
        }
    }

接下来看isAutowireCandidate()方法

@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
    throws NoSuchBeanDefinitionException {
    return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}

流程如下

1、先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断。SimpleAutowireCandidateResolver#isAutowireCandidate()

default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    return bdHolder.getBeanDefinition().isAutowireCandidate();
}

2、判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断。GenericTypeAwareAutowireCandidateResolver#isAutowireCandidate()

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    if (!super.isAutowireCandidate(bdHolder, descriptor)) {
        // If explicitly false, do not proceed with any other checks...
        return false;
    }
    return checkGenericTypeMatch(bdHolder, descriptor);
}

3、如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配。QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate()

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
    // 先执行上层判断匹配(第二步的泛型匹配),如果匹配成功,在自己匹配
    boolean match = super.isAutowireCandidate(bdHolder, descriptor);
    if (match) {
        // descriptor.getAnnotations()拿得是属性或方法参数前的注解,拿不到方法上的注解
        match = checkQualifiers(bdHolder, descriptor.getAnnotations());
        if (match) {
            MethodParameter methodParam = descriptor.getMethodParameter();
            if (methodParam != null) {
                Method method = methodParam.getMethod();
                if (method == null || void.class == method.getReturnType()) {
                    // methodParam.getMethodAnnotations()实际上拿得的是方法上的注解
                    match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
                }
            }
        }
    }
    return match;
}

大致流程图

image.png


版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门