25–Spring填充bean屬性及應(yīng)用生命周期接口

前面已經(jīng)分析了Spring創(chuàng)建實(shí)例和解決循環(huán)依賴的問題氛悬,今天繼續(xù)看實(shí)例創(chuàng)建完成之后的操作,填充bean的屬性及應(yīng)用生命周期接口

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

    // Instantiate the bean.
    // ① 實(shí)例化bean
    BeanWrapper instanceWrapper = null;
    // 注意factoryBeanInstanceCache是ConcurrentMap,remove方法會(huì)返回刪除的鍵值(如果不存在返回null)
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 如果factoryBeanInstanceCache沒有緩存對(duì)應(yīng)的BeanWrapper,則重新創(chuàng)建bean實(shí)例
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // ② 允許MergedBeanDefinitionPostProcessor后處理器修改已合并的bean定義粗悯。
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // ③ 提前緩存ObjectFactory以解決bean之間的循環(huán)依賴
    // mbd.isSingleton()->是否單例,Spring只解決單例bean的循環(huán)依賴問題
    // allowCircularReferences->是否允許循環(huán)依賴
    // isSingletonCurrentlyInCreation->該bean是否創(chuàng)建中
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // ④ 初始化bean實(shí)例 這里大家要與第①步區(qū)分開,到這里bean已經(jīng)完成了實(shí)例化,但是還沒有完成初始化的操作,例如bean的屬性填充
    Object exposedObject = bean;
    try {
        // 填充bean屬性
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化bean
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    // ⑤ 循環(huán)依賴檢查
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        // ⑥ 根據(jù)bean的作用域注冊(cè)bean
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    // ⑦ 返回bean實(shí)例
    return exposedObject;
}

第四步就是填充bean的屬性虚循。我們來看其過程

1.屬性填充的準(zhǔn)備工作
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // ① 前置判斷
    // 如果BeanWrapper對(duì)象為null,則說明沒有bean的實(shí)例
    if (bw == null) {
        // RootBeanDefinition中有屬性,但是bean的實(shí)例為空,拋出異常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // RootBeanDefinition中沒有屬性,直接返回
            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.
    // ② 應(yīng)用InstantiationAwareBeanPostProcessor處理器
    // 在設(shè)置屬性之前,給InstantiationAwareBeanPostProcessor一個(gè)修改bean狀態(tài)的機(jī)會(huì)
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 是否繼續(xù)填充bean屬性
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }

    // ③ 如果InstantiationAwareBeanPostProcessor停止了對(duì)bean屬性的填充,則直接返回
    if (!continueWithPropertyPopulation) {
        return;
    }

    // 獲取PropertyValues屬性
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // ④ 解析自動(dòng)裝配類型
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // byName注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // byType注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }

    // ⑤ 判斷是否有InstantiationAwareBeanPostProcessors處理器,并進(jìn)行處理
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                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;
            }
        }
    }

    // ⑥ 依賴檢查
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // ⑦ 應(yīng)用屬性
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

該方法最重要的就是對(duì)屬性填充方式判斷,byName样傍,byType和不開啟自動(dòng)注入横缔。Spring默認(rèn)是不開啟autowire的,需要在配置文件中配置default-autowire屬性衫哥,那么我們首先來分析不開啟自動(dòng)注入方式的屬性填充茎刚。(byName,byType需要用到一些注解方面的知識(shí)撤逢,我們留在以后分析)

2.不開啟自動(dòng)注入屬性填充
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // 1膛锭、 如果PropertyValues為空,直接返回
    if (pvs.isEmpty()) {
        return;
    }

    // 2、判斷安全管理器
    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
        ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }

    //MutablePropertyValues是PropertyValues接口的默認(rèn)實(shí)現(xiàn)類
    MutablePropertyValues mpvs = null;
    List<PropertyValue> original;

    // 3蚊荣、 獲取bean的屬性集合
    // 如果pvs是MutablePropertyValues的實(shí)例,MutablePropertyValues是PropertyValues的默認(rèn)實(shí)現(xiàn)
    if (pvs instanceof MutablePropertyValues) {
        // 將pvs轉(zhuǎn)換為MutablePropertyValues對(duì)象,并判斷mpvs是否已經(jīng)經(jīng)過轉(zhuǎn)換
        mpvs = (MutablePropertyValues) pvs;
        if (mpvs.isConverted()) {
            // 如果pvs已經(jīng)轉(zhuǎn)換過,則直接設(shè)置屬性值無需再次轉(zhuǎn)換
            try {
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        // 否則獲取原始PropertyValue集合
        original = mpvs.getPropertyValueList();
    }
    else {
        original = Arrays.asList(pvs.getPropertyValues());
    }

    // 4初狰、 獲取類型轉(zhuǎn)換器
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // 5、 通過深度拷貝,解析值引用
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    // 循環(huán)解析PropertyValues
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            // 獲取屬性名稱
            String propertyName = pv.getName();
            // 獲取原始屬性值
            Object originalValue = pv.getValue();
            // 解析原始屬性值
            // 當(dāng)注入集合屬性時(shí),如果指定了,value-type,如value-type="java.lang.String",
            // 那么resolveValueIfNecessary也會(huì)執(zhí)行類型的轉(zhuǎn)換操作
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            // isWritableProperty-->判斷屬性是否可寫,如果屬性不存在返回false
            // isNestedOrIndexedProperty-->判斷是否索引屬性或者嵌套屬性
            boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                // 類型轉(zhuǎn)換
                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.
            // 緩存已經(jīng)轉(zhuǎn)換過的值,避免再次轉(zhuǎn)換
            // 例如:當(dāng)通過FactoryBean注入屬性值時(shí) p:studentInfo="張三,25,三年二班",會(huì)有resolvedValue == originalValue
            if (resolvedValue == originalValue) {
                if (convertible) {
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                    !((TypedStringValue) originalValue).isDynamic() &&
                    !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }

    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // 7互例、設(shè)置屬性值.
    try {
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}
2.1 步驟簡(jiǎn)析
  • 嘗試從緩存中中獲取已經(jīng)解析過的屬性值
  • 如果未能從緩存中獲取奢入,則獲取原始的屬性值
  • 獲取類型轉(zhuǎn)換器
  • 循環(huán)所有原始屬性值,通過深度拷貝媳叨,解析值引用
  • 解析原始屬性值
  • 類型轉(zhuǎn)換
  • 設(shè)置屬性值

我們只分析其中的一些關(guān)鍵方法

2.2 resolveValueIfNecessary 解析屬性值
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
    // 1腥光、 RuntimeBeanReference->運(yùn)行時(shí)引用
    //   例如BeanA依賴BeanB,那么在配置文件中有通過配置ref標(biāo)簽進(jìn)行引用的,在解析BeanDefinition的時(shí)候,是不會(huì)直接實(shí)例化BeanB的,那么這個(gè)引用就是RuntimeBeanReference
    if (value instanceof RuntimeBeanReference) {
        RuntimeBeanReference ref = (RuntimeBeanReference) value;
        return resolveReference(argName, ref);
    }
    // 2、 RuntimeBeanNameReference->沒弄明白
    else if (value instanceof RuntimeBeanNameReference) {
        String refName = ((RuntimeBeanNameReference) value).getBeanName();
        refName = String.valueOf(doEvaluate(refName));
        if (!this.beanFactory.containsBean(refName)) {
            throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);
        }
        return refName;
    }
    // 3糊秆、 解析innerBean
    else if (value instanceof BeanDefinitionHolder) {
        // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
        BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
        return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
    }
    else if (value instanceof BeanDefinition) {
        // Resolve plain BeanDefinition, without contained name: use dummy name.
        BeanDefinition bd = (BeanDefinition) value;
        String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd);
        return resolveInnerBean(argName, innerBeanName, bd);
    }
    // 4柴我、 解析數(shù)組
    else if (value instanceof ManagedArray) {
        // May need to resolve contained runtime references.
        ManagedArray array = (ManagedArray) value;
        Class<?> elementType = array.resolvedElementType;
        if (elementType == null) {
            String elementTypeName = array.getElementTypeName();
            if (StringUtils.hasText(elementTypeName)) {
                try {
                    elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
                    array.resolvedElementType = elementType;
                }
                catch (Throwable ex) {
                    // Improve the message by showing the context.
                    throw new BeanCreationException(this.beanDefinition.getResourceDescription(),this.beanName,"Error resolving array type for "+argName, ex);
                }
            }
            else {
                elementType = Object.class;
            }
        }
        return resolveManagedArray(argName, (List<?>) value, elementType);
    }
    // 5、 解析List集合
    else if (value instanceof ManagedList) {
        // May need to resolve contained runtime references.
        return resolveManagedList(argName, (List<?>) value);
    }
    // 6扩然、 解析Set集合
    else if (value instanceof ManagedSet) {
        // May need to resolve contained runtime references.
        return resolveManagedSet(argName, (Set<?>) value);
    }
    // 7艘儒、 解析Map集合
    else if (value instanceof ManagedMap) {
        // May need to resolve contained runtime references.
        return resolveManagedMap(argName, (Map<?, ?>) value);
    }
    // 8、 解析Properties集合
    else if (value instanceof ManagedProperties) {
        Properties original = (Properties) value;
        Properties copy = new Properties();
        original.forEach((propKey, propValue) -> {
            if (propKey instanceof TypedStringValue) {
                propKey = evaluate((TypedStringValue) propKey);
            }
            if (propValue instanceof TypedStringValue) {
                propValue = evaluate((TypedStringValue) propValue);
            }
            if (propKey == null || propValue == null) {
                throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,
                        "Error converting Properties key/value pair for " + argName + ": resolved to null");
            }
            copy.put(propKey, propValue);
        });
        return copy;
    }
    // 9夫偶、 解析字符串
    else if (value instanceof TypedStringValue) {
        // Convert value to target type here.
        TypedStringValue typedStringValue = (TypedStringValue) value;
        Object valueObject = evaluate(typedStringValue);
        try {
            Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
            if (resolvedTargetType != null) {
                return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
            }
            else {
                return valueObject;
            }
        }
        catch (Throwable ex) {
            // Improve the message by showing the context.
            throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,
                    "Error converting typed String value for " + argName, ex);
        }
    }
    // 10界睁、 NullBean或者表達(dá)式
    else if (value instanceof NullBean) {
        return null;
    }
    else {
        return evaluate(value);
    }
}

該方法包含了對(duì)各種屬性值的解析,例如RuntimeBeanReference->運(yùn)行時(shí)引用兵拢,我們已經(jīng)在上一節(jié)分析過了翻斟。我們?cè)趯?duì)其中的解析List集合進(jìn)行一下分析,篇幅優(yōu)先其他的解析大家可以自行debug跟蹤分析说铃。

解析List集合屬性访惜,該方法也很簡(jiǎn)單循環(huán)并再次調(diào)用resolveValueIfNecessary方法進(jìn)行解析嘹履,將解析值加入List<Object>集合返回即可。

private List<?> resolveManagedList(Object argName, List<?> ml) {
    // 創(chuàng)建長(zhǎng)度為配置文件中指定的元素個(gè)數(shù)的List集合
    List<Object> resolved = new ArrayList<>(ml.size());
    for (int i = 0; i < ml.size(); i++) {
        // 循環(huán)解析元素,如果配置文件中指定了value-type,resolveValueIfNecessary過程中會(huì)對(duì)元素進(jìn)行類型轉(zhuǎn)換
        resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
    }
    return resolved;
}
2.3 convertForProperty 轉(zhuǎn)換屬性值
private Object convertForProperty(@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
    if (converter instanceof BeanWrapperImpl) {
        return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
    }
    else {
        PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
        MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
        return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
    }
}

調(diào)用convertForProperty方法執(zhí)行轉(zhuǎn)換前的準(zhǔn)本工作

public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
    // CachedIntrospectionResults-->緩存了PropertyDescriptor集合
    CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
    // PropertyDescriptor-->表示JavaBean類通過存儲(chǔ)器導(dǎo)出一個(gè)屬性债热。主要方法:
    // 1. getReadMethod()砾嫉,獲得用于讀取屬性值的方法
    // 2. getWriteMethod(),獲得用于寫入屬性值的方法
    PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
    if (pd == null) {
        throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,"No property '" + propertyName + "' found");
    }
    // 獲取類型轉(zhuǎn)換上下文
    TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
    if (td == null) {
        // 如果未能從緩存中獲取,則創(chuàng)建一個(gè)新的TypeDescriptor并緩存
        td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
    }
    // 轉(zhuǎn)換類型
    return convertForProperty(propertyName, null, value, td);
}

調(diào)用convertForProperty執(zhí)行轉(zhuǎn)換窒篱,但是真正的轉(zhuǎn)換操作委托給了TypeConverterDelegate執(zhí)行

public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
            @Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {

    // Custom editor for this type?
    // 1焕刮、判斷有無自定義屬性編輯器
    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

    ConversionFailedException conversionAttemptEx = null;

    // No custom editor but custom ConversionService specified?
    // 2、判斷有無自定義ConversionService
    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
    if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
        TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
        if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
            try {
                return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
            }
            catch (ConversionFailedException ex) {
                // fallback to default conversion logic below
                conversionAttemptEx = ex;
            }
        }
    }

    Object convertedValue = newValue;

    // Value not of required type?
    // ClassUtils.isAssignableValue(requiredType, convertedValue)-->判斷requiredType和convertedValue的class,是否相同,
    // 相同返回->true;否則返回->false
    // 3墙杯、 如果有自定義屬性編輯器或者通過解析出來的值類型與真實(shí)的值類型的class不同
    // 例如<property name="age" value="3"/>,我們需要將value轉(zhuǎn)換成int時(shí)
    if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
        if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
            TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
            if (elementTypeDesc != null) {
                Class<?> elementType = elementTypeDesc.getType();
                if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
                    convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                }
            }
        }
        if (editor == null) {
            editor = findDefaultEditor(requiredType);
        }
        convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
    }

    boolean standardConversion = false;

    // 4配并、執(zhí)行轉(zhuǎn)換
    if (requiredType != null) {
        // Try to apply some standard type conversion rules if appropriate.
        if (convertedValue != null) {
            // Object類型
            if (Object.class == requiredType) {
                return (T) convertedValue;
            }
            // 數(shù)組類型
            else if (requiredType.isArray()) {
                // Array required -> apply appropriate conversion of elements.
                if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
                    convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                }
                return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
            }
            // 集合類型
            else if (convertedValue instanceof Collection) {
                // Convert elements to target type, if determined.
                convertedValue = convertToTypedCollection((Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            }
            // map類型
            else if (convertedValue instanceof Map) {
                // Convert keys and values to respective target type, if determined.
                convertedValue = convertToTypedMap((Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            }

            // 注意:這里是新開啟的if,不接上面的else if
            // 如果經(jīng)過轉(zhuǎn)換過的值是數(shù)組類型,且其長(zhǎng)度只有1,那么只取其第0個(gè)作為最終轉(zhuǎn)換值
            if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
                convertedValue = Array.get(convertedValue, 0);
                standardConversion = true;
            }
            // 如果類型是String,并且是java的基本數(shù)據(jù)類型或者包裝類型
            // 包括 boolean, byte, char, short, int, long, float, double
            // 和 Boolean, Byte, Character, Short, Integer, Long, Float, Double
            // 那么直接調(diào)用toString()方法返回即可,注意convertedValue是Object類型,不是基本或包裝類型,所以是可以調(diào)用toString()方法的
            if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
                // We can stringify any primitive value...
                return (T) convertedValue.toString();
            }
            // 如果轉(zhuǎn)換值是String類的實(shí)例,但是我們又不能轉(zhuǎn)換為解析出來的requiredType的實(shí)例
            // 例如枚舉類型值的注入
            else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
                if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
                    try {
                        Constructor<T> strCtor = requiredType.getConstructor(String.class);
                        return BeanUtils.instantiateClass(strCtor, convertedValue);
                    }
                    // 刪除logger信息
                    catch (NoSuchMethodException ex) {}
                    catch (Exception ex) {}
                }
                String trimmedValue = ((String) convertedValue).trim();
                if (requiredType.isEnum() && "".equals(trimmedValue)) {
                    // It's an empty enum identifier: reset the enum value to null.
                    return null;
                }
                convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
                standardConversion = true;
            }
            // 數(shù)值類型
            else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
                convertedValue = NumberUtils.convertNumberToTargetClass((Number) convertedValue, (Class<Number>) requiredType);
                standardConversion = true;
            }
        }
        else {
            // convertedValue == null
            if (requiredType == Optional.class) {
                convertedValue = Optional.empty();
            }
        }

        // 5、 判定requiredType是否可從convertedValue轉(zhuǎn)換而來,并嘗試使用conversionService轉(zhuǎn)換,及處理轉(zhuǎn)換異常
        if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
            if (conversionAttemptEx != null) {
                // Original exception from former ConversionService call above...
                throw conversionAttemptEx;
            }
            else if (conversionService != null && typeDescriptor != null) {
                // ConversionService not tried before, probably custom editor found
                // but editor couldn't produce the required type...
                TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
                if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
                    return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
                }
            }

            // 到此為止,可以確定類型不匹配,無法轉(zhuǎn)換,拋出IllegalArgumentException/IllegalStateException
            StringBuilder msg = new StringBuilder();
            msg.append("錯(cuò)誤提示讓我刪了...");
            // 刪除了msg提示配置
            if (editor != null) {
                throw new IllegalArgumentException(msg.toString());
            }
            else {
                throw new IllegalStateException(msg.toString());
            }
        }
    }

    if (conversionAttemptEx != null) {
        if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
            throw conversionAttemptEx;
        }
    }

    // 6高镐、返回轉(zhuǎn)換值
    return (T) convertedValue;
}
2.4 setPropertyValues 設(shè)置屬性值
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException {

    List<PropertyAccessException> propertyAccessExceptions = null;

    // 獲取當(dāng)前bean的所有屬性值
    List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
            ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));

    // 循環(huán)并設(shè)置屬性值
    for (PropertyValue pv : propertyValues) {
        try {
            // This method may throw any BeansException, which won't be caught
            // here, if there is a critical failure such as no matching field.
            // We can attempt to deal only with less serious exceptions.
            setPropertyValue(pv);
        }
        catch (NotWritablePropertyException ex) {
            if (!ignoreUnknown) {
                throw ex;
            }
            // Otherwise, just ignore it and continue...
        }
        catch (NullValueInNestedPathException ex) {
            if (!ignoreInvalid) {
                throw ex;
            }
            // Otherwise, just ignore it and continue...
        }
        catch (PropertyAccessException ex) {
            if (propertyAccessExceptions == null) {
                propertyAccessExceptions = new ArrayList<>();
            }
            propertyAccessExceptions.add(ex);
        }
    }

    // If we encountered individual exceptions, throw the composite exception.
    if (propertyAccessExceptions != null) {
        PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
        throw new PropertyBatchUpdateException(paeArray);
    }
}

調(diào)用setPropertyValue設(shè)置單個(gè)屬性值

public void setPropertyValue(PropertyValue pv) throws BeansException {
    PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
    if (tokens == null) {
        String propertyName = pv.getName();
        AbstractNestablePropertyAccessor nestedPa;
        try {
            nestedPa = getPropertyAccessorForPropertyPath(propertyName);
        }
        catch (NotReadablePropertyException ex) {
            throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
                    "Nested property in path '" + propertyName + "' does not exist", ex);
        }
        tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
        if (nestedPa == this) {
            pv.getOriginalPropertyValue().resolvedTokens = tokens;
        }
        nestedPa.setPropertyValue(tokens, pv);
    }
    else {
        setPropertyValue(tokens, pv);
    }
}

調(diào)用nestedPa.setPropertyValue(tokens, pv);執(zhí)行轉(zhuǎn)換前的判斷

protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
    // 設(shè)置配置文件中的key:value對(duì),例如.propertis中的屬性
    if (tokens.keys != null) {
        processKeyedProperty(tokens, pv);
    }
    // 設(shè)置本地屬性
    else {
        processLocalProperty(tokens, pv);
    }
}

調(diào)動(dòng)processLocalProperty設(shè)置本地屬性值

private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
    PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
    // PropertyHandler為null,或者方法不可寫的時(shí)候.
    if (ph == null || !ph.isWritable()) {
        //返回是否為可選值溉旋,即在目標(biāo)類上不存在相應(yīng)的屬性時(shí)將被忽略。
        if (pv.isOptional()) {
            return;
        }
        else {
            throw createNotWritablePropertyException(tokens.canonicalName);
        }
    }

    Object oldValue = null;
    try {
        Object originalValue = pv.getValue();
        Object valueToApply = originalValue;
        if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
            if (pv.isConverted()) {
                valueToApply = pv.getConvertedValue();
            }
            else {
                if (isExtractOldValueForEditor() && ph.isReadable()) {
                    try {
                        oldValue = ph.getValue();
                    }
                    // 省略異常打印信息...
                    catch (Exception ex) {}
                }
                valueToApply = convertForProperty(tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
            }
            pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
        }
        // 設(shè)置屬性值嫉髓,即調(diào)用bean中的set方法
        ph.setValue(valueToApply);
    }
    catch (TypeMismatchException ex) {
        throw ex;
    }
    catch (InvocationTargetException ex) {
        PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
                getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
        if (ex.getTargetException() instanceof ClassCastException) {
            throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
        }
        else {
            Throwable cause = ex.getTargetException();
            if (cause instanceof UndeclaredThrowableException) {
                // May happen e.g. with Groovy-generated methods
                cause = cause.getCause();
            }
            throw new MethodInvocationException(propertyChangeEvent, cause);
        }
    }
    catch (Exception ex) {
        PropertyChangeEvent pce = new PropertyChangeEvent(getRootInstance(), this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
        throw new MethodInvocationException(pce, ex);
    }
}
public void setValue(final @Nullable Object value) throws Exception {
    final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
            ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
            this.pd.getWriteMethod());
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(writeMethod);
            return null;
        });
        try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
                    writeMethod.invoke(getWrappedInstance(), value), acc);
        }
        catch (PrivilegedActionException ex) {
            throw ex.getException();
        }
    }
    else {
        ReflectionUtils.makeAccessible(writeMethod);
        // 通過Method的invoke方法設(shè)置屬性值低滩,到這里就會(huì)調(diào)動(dòng)bean中的set方法,為bean設(shè)置屬性值
        writeMethod.invoke(getWrappedInstance(), value);
    }
}
3.initializeBean初始化bean

在完成bean屬性填充工作之后岩喷,距離bean實(shí)例的創(chuàng)建完成就不遠(yuǎn)了。接下來調(diào)用initializeBean方法监憎,完成有關(guān)bean的生命周期的部分操作纱意,例如應(yīng)用bean的處理器、調(diào)用bean的初始化方法鲸阔、調(diào)用BeanNameAware接口等偷霉。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 1、調(diào)用各種AwareMethods
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    // 2褐筛、應(yīng)用bean前置處理器
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    // 3类少、調(diào)用bean的init_method初始化方法
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName,"Invocation of init method failed", ex);
    }
    // 4、應(yīng)用bean后置處理器
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

在該方法中一共執(zhí)行了四部操作渔扎,接下來我們逐步分析其中的操作硫狞。

  • 1、調(diào)用各種AwareMethods
/**
 * 調(diào)用AwareMethods
 * @param beanName
 * @param bean
 */
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        // 1晃痴、調(diào)用BeanNameAware接口
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        // 2残吩、調(diào)用BeanClassLoaderAware接口
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        // 3、調(diào)用BeanFactoryAware接口
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}
  • 2倘核、應(yīng)用bean前置處理器
/**
 * 在bean完成初始化之前應(yīng)用BeanPostProcessors
 * @param existingBean the new bean instance
 * @param beanName the name of the bean
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
  • 3泣侮、調(diào)用bean的init_method初始化方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {

    // 1、調(diào)用InitializingBean接口
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    // 2紧唱、調(diào)用init-method
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

具體的調(diào)用通過method.invoke方法執(zhí)行活尊,不再粘貼隶校。

  • 4、應(yīng)用bean后置處理器
/**
 * 在bean完成初始化之后應(yīng)用BeanPostProcessors
 * @param existingBean the new bean instance
 * @param beanName the name of the bean
 * @return
 * @throws BeansException
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蛹锰,一起剝皮案震驚了整個(gè)濱河市深胳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宁仔,老刑警劉巖稠屠,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異翎苫,居然都是意外死亡权埠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門煎谍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攘蔽,“玉大人,你說我怎么就攤上這事呐粘÷祝” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵作岖,是天一觀的道長(zhǎng)唆垃。 經(jīng)常有香客問我,道長(zhǎng)痘儡,這世上最難降的妖魔是什么辕万? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮沉删,結(jié)果婚禮上渐尿,老公的妹妹穿的比我還像新娘。我一直安慰自己矾瑰,他們只是感情好砖茸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著殴穴,像睡著了一般凉夯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上采幌,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天恍涂,我揣著相機(jī)與錄音,去河邊找鬼植榕。 笑死再沧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尊残。 我是一名探鬼主播炒瘸,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淤堵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了顷扩?” 一聲冷哼從身側(cè)響起拐邪,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隘截,沒想到半個(gè)月后扎阶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡婶芭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年东臀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片犀农。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惰赋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呵哨,到底是詐尸還是另有隱情赁濒,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布孟害,位于F島的核電站拒炎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏挨务。R本人自食惡果不足惜击你,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耘子。 院中可真熱鬧,春花似錦球切、人聲如沸谷誓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捍歪。三九已至,卻和暖如春鸵钝,著一層夾襖步出監(jiān)牢的瞬間糙臼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工恩商, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留变逃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓怠堪,卻偏偏與公主長(zhǎng)得像揽乱,于是被迫代替她去往敵國(guó)和親名眉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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

  • 一個(gè)團(tuán)隊(duì)靠什么在激烈的競(jìng)爭(zhēng)中取勝凰棉?有這樣一種說法:“一頭獅子帶領(lǐng)一群羊可以打敗一頭羊帶領(lǐng)的一群獅子”也有一與種說法...
    5c7dc5269e5e閱讀 1,104評(píng)論 0 0
  • 其實(shí)沒人能告訴你 放棄一個(gè)人到底應(yīng)該怎么做 你只能自己熬過無數(shù)黑漆漆的夜晚 然后第二天照常起床 假裝什么事也沒發(fā)生...
    伊若舞閱讀 318評(píng)論 6 0
  • 就像上課一樣我都會(huì)在后幾天把內(nèi)容發(fā)出來,這次行動(dòng)派讀書會(huì)的線下聚會(huì)分享我也是沒有第一時(shí)間發(fā)出來或舞。 早上早早的去了一...
    紫菜姐閱讀 193評(píng)論 1 4
  • 今天是普通的一天或者可以說是普通的周末荆姆,實(shí)話說,我不喜歡周末嚷那,因?yàn)楹⒆觽兌家诩野恚蠹叶?..... ...
    瑪?shù)铝?018閱讀 635評(píng)論 6 1