1. 程式人生 > >26--Spring建立Bean的過程(八),bean屬性填充應用屬性值

26--Spring建立Bean的過程(八),bean屬性填充應用屬性值

前兩個小節,已經分析了bean屬性的解析和轉換,轉換完之後,就可以應用屬性了,我們的例項中用的都是Setter方法注入,那麼自然會呼叫bean屬性的set方法對屬性進行注入。

開啟AbstractAutowireCapableBeanFactory類的applyPropertyValues方法,開始分析

// ⑦設定屬性值.
try {
	bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
1. 迴圈獲取到的PropertyValue並設定屬性值
public void setPropertyValues(PropertyValues pvs,
boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException { List<PropertyAccessException> propertyAccessExceptions = null; // 獲取當前bean的所有屬性值 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList
() : Arrays.asList(pvs.getPropertyValues())); // 迴圈並設定屬性值 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); } }

至此我們已經得到了配置檔案中所有PropertyValue的集合,然後通過迴圈逐步將其值設定到bean中。

2.獲取PropertyTokenHolder物件並判斷應該設定key-value屬性還是本地屬性
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);
    }
}
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
    // 設定配置檔案中的key:value對,例如.propertis中的屬性
    if (tokens.keys != null) {
        processKeyedProperty(tokens, pv);
    }
    // 設定本地屬性
    else {
        processLocalProperty(tokens, pv);
    }
}
3.設定本地屬性
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
    PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
    // PropertyHandler為null,或者方法不可寫的時候.
    if (ph == null || !ph.isWritable()) {
        //返回是否為可選值,即在目標類上不存在相應的屬性時將被忽略。
        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);
        }
        // 設定屬性
        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);
    }
}
4.設定屬性
public void setValue(final @Nullable Object value) throws Exception {
	// 獲取可寫方法,例如javaBean中的setXXX()方法
    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方法,通過反射方法為bean設定值
        writeMethod.invoke(getWrappedInstance(), value);
    }
}
5.總結

設定屬性的大體流程還是比較簡單的,首先獲取已經轉換的所有的配置檔案中bean的屬性;然後迴圈獲取到的屬性為javaBean設定值;獲取javaBean的可寫方法;通過Method的invoke方法,利用java的反射機制為javaBean設定值。