5、Spring依賴解析實現

Spring對BeanFactory底層的最終實現是DefaultListableBeanFactory,DefaultListableBeanFactory對resolveDependency方法實現的源碼以下。java

/**
     * @param descriptor         字段或方法的依賴描述信息
     * @param requestingBeanName 須要注入依賴的 bean 的名稱
     * @param autowiredBeanNames 須要注入的依賴的 bean 名稱的集合,解析的結果會存放該集合中
     * @param typeConverter      類型轉換
     * @return
     * @throws BeansException
     */
    @Override
    @Nullable
    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()) {
            // 解析 Optional 依賴
            return createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class == descriptor.getDependencyType() ||
                ObjectProvider.class == descriptor.getDependencyType()) {
            // 解析 ObjectFactory 或 ObjectProvider 依賴
            return new DependencyObjectProvider(descriptor, requestingBeanName);
        } else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            // 解析 javax.inject.Provider 註解標註的依賴
            return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
        } else {
            // 懶加載的對象返回代理對象
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                    descriptor, requestingBeanName);
            if (result == null) {
                // 其餘對象進行解析
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }

解析依賴的方法,根據不一樣的依賴類型使用不一樣的解析方式。對於Optional、ObjectFactory、ObjectProvider依賴類型,因爲須要解析的是其泛型的實際類型,所以Spring會將依賴描述信息從新包裝爲另外一個DependencyDescriptor ,而後再解析。而Java規範JSR-330中註解javax.inject.Provider的處理則只是將實現委託給另外一個類處理。對於不一樣類型的依賴解析,最終都會調用doResolveDependency方法。以Optional類型的解析方法createOptionalDependency爲例源碼以下ide

private Optional<?> createOptionalDependency(
            DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {

        // 包裝依賴描述信息,解析依賴的類型時會將嵌套層次加1
        // 例如原來要解析的類型是 Optional<T> 的原始類型,嵌套層次加1後會解析泛型類型的實際類型 T
        DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
            @Override
            public boolean isRequired() {
                return false;
            }

            @Override
            public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
                return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :
                        super.resolveCandidate(beanName, requiredType, beanFactory));
            }
        };
        // 而後真正解析依賴
        Object result = doResolveDependency(descriptorToUse, beanName, null, null);
        // 再將解析出的依賴包裝到 Optional 中
        return (result instanceof Optional ? (Optional<?>) result : Optional.ofNullable(result));
    }

進入doResolveDependency方法ui

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        ... 省略部分代碼
            // 快捷解析依賴
            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());
                try {
                    // 將結果進行類型轉換
                    return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
                } catch (UnsupportedOperationException ex) {
                    ... 省略部分代碼
                }
            }

            // 嘗試解析包含多個 bean 的依賴對象
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                return multipleBeans;
            }

            // 查找所需類型的依賴
            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) {
                // 存在多個類型相同的依賴,肯定使用哪一個依賴
                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);
            }
            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;
    }

對於集合類型以及單一類型,最終都會調用findAutowireCandidates方法查找自動裝配的候選對象,對於集合類型會把查找到的候選對象包裝爲對應所需的類型,對於單一類型則須要確認最終使用哪一個依賴。進入findAutowireCandidates方法this

protected Map<String, Object> findAutowireCandidates(
            @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
        // 查找 Spring 中給定類型的 bean 名稱
        String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this, requiredType, true, descriptor.isEager());
        Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
        // 先解析 Spring 中游離的對象,若是類型和所需類型匹配則加入到結果中
        for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
            Class<?> autowiringType = classObjectEntry.getKey();
            if (autowiringType.isAssignableFrom(requiredType)) {
                Object autowiringValue = classObjectEntry.getValue();
                autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
                if (requiredType.isInstance(autowiringValue)) {
                    result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                    break;
                }
            }
        }
        // 而後解析 Spring 中註冊 BeanDefinition 中的名稱
        for (String candidate : candidateNames) {
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
                // 依賴非 bean 自身,而且 bean 能夠做爲候選項,加入到結果中
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }
        ... 省略回退處理代碼,和上述候選名稱循環相似
        return result;
    }

候選對象的獲取主要有兩個來源,一個是遊離對象,一個是Spring中的bean,Spring 根據類型獲取到對應的實例後添加到返回結果。這也印證了前面文章所說的依賴注入的依賴來源。須要留意的是對isAutowireCandidate方法的調用,isAutowireCandidate方法用於判斷一個一個對象是否能夠做爲候選項,其內部出了判斷bean定義中是否能夠做爲候選項的標識,還會判斷泛型、@Qualifier 等。對於單一類型的依賴解析,若是查找到了多個bean,則須要判斷到底使用哪個bean做爲結果,進入determineAutowireCandidate方法lua

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        // 先根據 primary 判斷
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }
        // primary 不存在,則根據優先級判斷
        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();
            // 依賴爲遊離對象或指定依賴的 bean 名稱匹配,直接返回
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }

這裏優先選擇標記 primary 爲 true 的 bean,若是都沒有標註則會選擇一個優先級最高的 bean,若是存在多個優先級相同的 bean 會拋出異常。最後會將遊離對象或和依賴的名稱匹配的 bean 做爲結果進行返回。代理

總結

Spring 依賴解析會優先根據 @Value 註解進行解析,而且支持多種類型。對於類型爲 Optional、ObjectFactory 的依賴 Spring 會將依賴包裝後返回,其餘類型又分爲集合類型和單一類型,對於集合類型 Spring 查找對全部依賴後直接包裝爲對應的類型返回便可,對於單一類型 Spring 會優先考慮 primary、最高優先級、和所需 bean 名稱匹配的 bean。code

相關文章
相關標籤/搜索