spring容器之bean的屬性填充

在我們剛學(xué)習(xí)spring對bean的創(chuàng)建時,我們在方法#doCreateBean()方法中,其主要通過創(chuàng)建bean和一些初始化工作,大概有4個過程分別是:

  • 調(diào)用#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法,來進(jìn)行bean的創(chuàng)建
  • 對于單例模式的bean進(jìn)行循環(huán)依賴的檢查
  • 通過調(diào)用#populateBean(beanName, mbd, instanceWrapper)來實現(xiàn)對剛創(chuàng)建的bean進(jìn)行屬性的填充
  • 最后調(diào)用#initializeBean(beanName, exposedObject, mbd)完成bean的初始化

關(guān)于bean的創(chuàng)建我們在前面的篇章中已經(jīng)完成了,接下來我們看看對于已完成bean的屬性的填充,直接來看代碼:

AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //沒有被封裝的bean實例
    if (bw == null) {
        //如果有屬性,則拋出BeanCreationException異常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            //沒有可填充的屬性
            return;
        }
    }

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    //1.在屬性填充前,給InstantiationAwareBeanPostProcessor最后一次來改變bean的機(jī)會
    boolean continueWithPropertyPopulation = true;
    //通過mbd.isSynthetic()來判斷當(dāng)前bean的定義是否是合成的,而不是由應(yīng)用來定義的
    //通過hasInstantiationAwareBeanPostProcessors來判斷當(dāng)前bean是否持有 InstantiationAwareBeanPostProcessor
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        //循環(huán)遍歷beanPostProcessors
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //如果為InstantiationAwareBeanPostProcessor類型的
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                //賦值即可
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                //返回的值為是否為繼續(xù)填充bean
                //postProcessAfterInstantiation:如果應(yīng)該在 bean上面設(shè)置屬性則返回 true,否則返回 false,但是一般默認(rèn)為true
                //如果返回false的話,將會阻止在此 Bean實例上調(diào)用任何后續(xù)的InstantiationAwareBeanPostProcessor實例
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    //如果后續(xù)處理器發(fā)出停止填充命令千贯,則終止后續(xù)操作
    if (!continueWithPropertyPopulation) {
        return;
    }
    //2.從rootBeanDefinition中獲取bean的屬性值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    //獲取resolvedAutowireMode的編碼
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //如果編碼為AUTOWIRE_BY_NAME為1或者AUTOWIRE_BY_TYPE為2
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        //對PropertyValues屬性進(jìn)行封裝成MutablePropertyValues對象
        //因為MutablePropertyValues主要是可以對構(gòu)造函數(shù)進(jìn)行深度的拷貝,以及屬性的操作,這樣可以保證我們的屬性值是獨立的
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        //根據(jù)名稱自動注入
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        //根據(jù)類型自動注入
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
    //是否已經(jīng)初始化好后置處理器
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    //是否需要依賴檢查
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    //3.bean的后置處理過程
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        //遍歷BeanPostProcessor進(jìn)行處理
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                //對所有需要依賴檢查的屬性進(jìn)行后置處理
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                //從BeanWrapper中進(jìn)行PropertyDescriptor結(jié)果集的提取
                //對于PropertyDescriptor:描述一個java Bean的屬性,可以通過一對方法可以提取一個屬性
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }//4.依賴檢查
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        //依賴檢查,其中對應(yīng)的是我們配置文件的屬性depens -on屬性
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }
    //5. 將屬性應(yīng)用到bean中
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

簡單的梳理下該方法的流程:

  • 在1處,通過hasInstantiationAwareBeanPostProcessors屬性來判斷,在屬性填充前,給InstantiationAwareBeanPostProcessor最后一次來改變bean的機(jī)會,此過程可以控制是否繼續(xù)進(jìn)行屬性的填充

  • 在2處,根據(jù)AbstractBeanDefinition#getResolvedAutowireMode()返回的值來判斷是以什么樣的方式注入的,然后統(tǒng)一存放在PorpertyValues中.

  • 根據(jù)名稱來自動注入:autowireByName(beanName, mbd, bw, newPvs);

  • 根據(jù)類型來自動注入: autowireByType(beanName, mbd, bw, newPvs);

  • 在3處,進(jìn)行后置處理

  • 在4處,需進(jìn)行依賴檢查

  • 在5處,將屬性應(yīng)用到bean中

接下來我們分別來看上述流程的每一個詳細(xì)的過程

根據(jù)不同的值來自動注入

在spring中是主要通過兩種不同的類型來注入的,是根據(jù)AbstractBeanDefinition#getResolvedAutowireMode()方法的值來做判斷,來看代碼:

//<1>獲取resolvedAutowireMode的編碼
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //如果編碼為AUTOWIRE_BY_NAME為1或者AUTOWIRE_BY_TYPE為2
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        //對PropertyValues屬性進(jìn)行封裝成MutablePropertyValues對象
        //因為MutablePropertyValues主要是可以對構(gòu)造函數(shù)進(jìn)行深度的拷貝,以及屬性的操作,這樣可以保證我們的屬性值是獨立的
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        //根據(jù)名稱自動注入
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        //根據(jù)類型自動注入
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

這就是這段根據(jù)不同類型來注入的部分代碼,我們來看<1>處:

AbstractBeanDefinition.java
private int autowireMode = AUTOWIRE_NO;
public int getResolvedAutowireMode() {
    if (this.autowireMode == AUTOWIRE_AUTODETECT) {
        // Work out whether to apply setter autowiring or constructor autowiring.
        // If it has a no-arg constructor it's deemed to be setter autowiring,
        // otherwise we'll try constructor autowiring.
        Constructor<?>[] constructors = getBeanClass().getConstructors();
        for (Constructor<?> constructor : constructors) {
            if (constructor.getParameterCount() == 0) {
                return AUTOWIRE_BY_TYPE;
            }
        }
        return AUTOWIRE_CONSTRUCTOR;
    }
    else {
        return this.autowireMode;
    }
}

這點代碼主要的作用就是獲取一個注入的類型,如果返回的值為1,則是通過名稱去注入,如果是2,則是通過類型去注入,我們來看根據(jù)名稱注入的過程:

autowireByName(根據(jù)名稱去注入)

該方法是在#autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs)中,接著看:

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //<1>.在bw中尋找需要注入的屬性名稱
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍歷處理
    for (String propertyName : propertyNames) {
        //如果容器中存在相關(guān)bean的名稱
        if (containsBean(propertyName)) {
            //遞歸初始化相關(guān)的bean
            Object bean = getBean(propertyName);
            //給指定名稱屬性綁定值
            pvs.add(propertyName, bean);
            //給相關(guān)依賴的bean注冊屬性
            registerDependentBean(propertyName, beanName);
            if (logger.isTraceEnabled()) {
                logger.trace("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                        "' by name: no matching bean found");
            }
        }
    }
}

該方法邏輯很清晰,首先尋找需要進(jìn)行綁定屬性的名稱,也就是上述代碼中的<1>處的方法,代碼如下:

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    Set<String> result = new TreeSet<>();
    //從beanDefinition中獲取屬性值
    PropertyValues pvs = mbd.getPropertyValues();
    PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    //遍歷處理
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null //有可寫的方法
                && !isExcludedFromDependencyCheck(pd) //依賴檢測沒有被忽略的
                && !pvs.contains(pd.getName())//在pvs中不包含該屬性名
                && !BeanUtils.isSimpleProperty(pd.getPropertyType())) {//不是簡單型的類型
            //添加
            result.add(pd.getName());
        }
    }
    return StringUtils.toStringArray(result);
}

獲取到了屬性的簡易名稱,接著是遞歸處理和給bean設(shè)置屬性值,在綁定的過程中可能會有依賴問題的處理,那么我們當(dāng)然還是先要給依賴的bean進(jìn)行相關(guān)屬性的設(shè)置,看代碼:

DefaultSinglegtonBeanRegistry.java
/**保存的是依賴beanName之間的映射關(guān)系*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/**
 * 給當(dāng)前bean注冊一個依賴的bean
 * @param beanName 當(dāng)前要創(chuàng)建的bean
 * @param dependentBeanName 當(dāng)前bean所依賴的bean的名字
 */
public void registerDependentBean(String beanName, String dependentBeanName) {
    //獲取原始beanName
    String canonicalName = canonicalName(beanName);
    // 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }
    //同上
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}
根據(jù)類型自動注入(autowireByType)

關(guān)于類型注入是通過#autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) 方法來完成自動注入的,直接看代碼:

protected void autowireByType(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //獲取自定義的TypeConverter實例
    //主要的作用是代替PropertyEditor機(jī)制
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //獲取非簡單的屬性名稱(也就是在bw中去獲取需要依賴注入的屬性名稱)
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍歷處理
    for (String propertyName : propertyNames) {
        try {
            //獲取PropertyDescriptor實例
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            //不要通過類型去嘗試著注入,因為它可能不是一個簡單的屬性,可能是多重屬性的依賴關(guān)系
            if (Object.class != pd.getPropertyType()) {
                //探測指定屬性的set方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                // 解析指定beanName的屬性所匹配的值,并把解析到的屬性名稱存儲在autowiredBeanNames中
                // 當(dāng)屬性存在多個封裝bean時將會找到所有匹配的bean并將其注入
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                //遍歷處理,并注冊相關(guān)依賴的bean的屬性
                for (String autowiredBeanName : autowiredBeanNames) {
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                //清空autowiredBeanNames數(shù)組
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

我們可以發(fā)現(xiàn),通過名稱和類型實現(xiàn)自動屬性的注入很類似,首先都是在bw中去尋找需要依賴注入的屬性,然后就是遍歷處理匹配bean進(jìn)行屬性的設(shè)置,最后對于依賴同樣也是做了處理,在根據(jù)類型去自動注入的過程中,有一個方法需要注意#resolveDependency(desc, beanName, autowiredBeanNames, converter),該方法主要是在注入前完成一些依賴解析工作,代碼如下:

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    //獲取一個ParameterNameDiscoverer實例
    //初始化方法所需的參數(shù)
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    //如果注入的是Optional類型,通過createOptionalDependency來處理
    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);
    }
    //如果是javaxInjectProviderClass類型的依賴,需要做特殊的處理操作
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    }
    //
    else {
        //通過#getLazyResolutionProxyIfNecessary(...)方法為實際依賴目標(biāo)的延遲解析構(gòu)建代理混聊。
        //默認(rèn)是null
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
            //<...>這里是通用的處理邏輯
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

上面方法的處理過程中,我們可以發(fā)現(xiàn)真正的核心在<...>處,接著看:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    //獲取一個注入點實例
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        // 針對給定的工廠給定一個快捷實現(xiàn)的方式臭杰,例如考慮一些預(yù)先解析的信息
        // 在進(jìn)入所有bean的常規(guī)類型匹配算法之前,解析算法將首先嘗試通過此方法解析快捷方式。
        // 子類可以覆蓋此方法
        Object shortcut = descriptor.resolveShortcut(this);
        //如果存在此快捷信息,則返回
        if (shortcut != null) {
            return shortcut;
        }
        //獲取依賴的類型
        Class<?> type = descriptor.getDependencyType();
        //此處主要是用于支持spring的@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) {
                // 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()));
            }
        }
        //解析復(fù)合的bean,實質(zhì)還是解析bean的屬性
        //不過考慮到了map array list等類型的
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        //查找匹配類型相同的bean實例
        // 返回的類型結(jié)構(gòu)為:key = 匹配的beanName隔嫡,value = beanName對應(yīng)的實例化bean
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        //沒找到,檢驗@autowire 的require是否為 true
        if (matchingBeans.isEmpty()) {
            //如果的require為true且沒有找到,直接拋raiseNoMatchingBeanFound異常
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;
        //找到了,確定給定bean的autowire的候選者
        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;
                }
            }
            //最后從matchingBeans取出
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            //已經(jīng)確認(rèn)了只有一個匹配項
            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 {
        //把它設(shè)置為一個注入點
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

到這里我們的屬性填充基本上完事,按照我們的方法populateBean(...)的大致流程完成屬性填充之后,接著是進(jìn)行后置處理操作,這里我們先放過,后續(xù)來說,接下來我們來看一下將屬性應(yīng)用到bean中的過程:

applyPropertyValues

在populateBean(...)的代碼片段中,首先是從beanDefinition中獲取到屬性的值,接著對PropertyValues屬性值進(jìn)行了封裝成MutablePropertyValues的對象,經(jīng)過一系列的處理最后通過#applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) 方法將屬性應(yīng)用到具體的bean中,我們來看代碼實現(xiàn):

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    if (pvs.isEmpty()) {
        return;
    }

    //設(shè)置當(dāng)前BeanWrapperImpl的SecurityContext環(huán)境
    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
        ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }
    //一種是MutablePropertyValues類型的
    MutablePropertyValues mpvs = null;
    //一種是original的類型的
    List<PropertyValue> original;
    //獲取original類型
    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        //如果已經(jīng)轉(zhuǎn)換了類型
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                //給相應(yīng)的實例設(shè)置屬性值,這里才是依賴注入的真正實現(xiàn)的地方
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        original = mpvs.getPropertyValueList();
    }
    else {
        //如果pvs不是MutablePropertyValues類型的,那么直接使用原始的屬性獲取方法
        original = Arrays.asList(pvs.getPropertyValues());
    }
    //獲取自定義TypeConverter類型
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    //獲取解析器
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    //遍歷屬性,同時將屬性轉(zhuǎn)換為對應(yīng)類的對應(yīng)屬性的類型
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        //轉(zhuǎn)換對應(yīng)屬性的屬性值
        else {
            String propertyName = pv.getName();
            Object originalValue = pv.getValue();
            //轉(zhuǎn)換屬性值,比如:將當(dāng)前的引用轉(zhuǎn)換為IOC容器中的實例化對象的引用
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            //判斷屬性值是否可以轉(zhuǎn)換
            boolean convertible = bw.isWritableProperty(propertyName) &&
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            //通過自定義的TypeConverter類型進(jìn)行屬性值的轉(zhuǎn)換
            if (convertible) {
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            // Possibly store converted value in merged bean definition,
            // in order to avoid re-conversion for every created bean instance.
            //對轉(zhuǎn)換后的屬性值進(jìn)行保存,避免之后每次創(chuàng)建實例重復(fù)轉(zhuǎn)換工作
            if (resolvedValue == originalValue) {
                if (convertible) {
                    //設(shè)置轉(zhuǎn)換后的值給pv
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            // 屬性是可轉(zhuǎn)換的涂屁,且屬性原始值是字符串類型书在,且屬性的原始類型值不是
            // 動態(tài)生成的字符串,且屬性的原始值不是集合或者數(shù)組類型
            else if (convertible && originalValue instanceof TypedStringValue &&
                    !((TypedStringValue) originalValue).isDynamic() &&
                    !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                //進(jìn)行設(shè)置
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            //沒有轉(zhuǎn)換
            else {
                //重新封裝屬性值
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    //對轉(zhuǎn)換過的屬性值進(jìn)行標(biāo)記
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    //這里是屬性依賴注入的實現(xiàn)點
    try {
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

上面就是applyPropertyValues方法的分析過程其主要是圍繞著兩個點來展開:

  • 在進(jìn)行屬性值的注入時,如果屬性值不需要轉(zhuǎn)換,那么直接進(jìn)行注入即可.
  • 當(dāng)需要對屬性值進(jìn)行轉(zhuǎn)換時,首先是轉(zhuǎn)換成對應(yīng)類的屬性的屬性值,接著設(shè)置,最后完成注入

大致的就是分為這兩類進(jìn)行屬性值的注入,如果需要轉(zhuǎn)換屬性值,這里涉及到了轉(zhuǎn)換的方法#resolveValueIfNecessary(Object argName, @Nullable Object value),該方法我們后面詳細(xì)來說,這里大家先知道一下,到這里我們已經(jīng)完成了doCreateBean(...)的第二個階段,我們的屬性填充已經(jīng)完成...

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拆又,一起剝皮案震驚了整個濱河市蕊温,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遏乔,老刑警劉巖义矛,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盟萨,居然都是意外死亡凉翻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門捻激,熙熙樓的掌柜王于貴愁眉苦臉地迎上來制轰,“玉大人,你說我怎么就攤上這事胞谭±龋” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵丈屹,是天一觀的道長调俘。 經(jīng)常有香客問我,道長旺垒,這世上最難降的妖魔是什么彩库? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮先蒋,結(jié)果婚禮上秸谢,老公的妹妹穿的比我還像新娘绣溜。我一直安慰自己屁奏,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布窥翩。 她就那樣靜靜地躺著,像睡著了一般鳞仙。 火紅的嫁衣襯著肌膚如雪寇蚊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天繁扎,我揣著相機(jī)與錄音幔荒,去河邊找鬼糊闽。 笑死梳玫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的右犹。 我是一名探鬼主播提澎,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼念链!你這毒婦竟也來了盼忌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤掂墓,失蹤者是張志新(化名)和其女友劉穎谦纱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體君编,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡跨嘉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吃嘿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祠乃。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兑燥,靈堂內(nèi)的尸體忽然破棺而出亮瓷,到底是詐尸還是另有隱情,我是刑警寧澤降瞳,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布嘱支,位于F島的核電站,受9級特大地震影響挣饥,放射性物質(zhì)發(fā)生泄漏斗塘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一亮靴、第九天 我趴在偏房一處隱蔽的房頂上張望馍盟。 院中可真熱鬧,春花似錦茧吊、人聲如沸贞岭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞄桨。三九已至话速,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芯侥,已是汗流浹背泊交。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留柱查,地道東北人廓俭。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像唉工,于是被迫代替她去往敵國和親研乒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容