Spring 源码粘贴3

来源:互联网 发布:抗日网络剧牺牲 编辑:程序博客网 时间:2024/06/04 18:06

回到上面的那个注入发生第一现场setPropertyValues(),看看里面的具体实现setPropertyValue()

bw.setPropertyValues()此方法的实现在AbstractPropertyAccessor,原来的BeanWrapperImpl从2.5开始就不提供这些方法了.

public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)throws BeansException {...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);}...}

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 {String propertyName = tokens.canonicalName;String actualName = tokens.actualName;if (tokens.keys != null) {// Apply indexes and map keys: fetch value for all keys but the last one.PropertyTokenHolder getterTokens = new PropertyTokenHolder();getterTokens.canonicalName = tokens.canonicalName;getterTokens.actualName = tokens.actualName;getterTokens.keys = new String[tokens.keys.length - 1];System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);Object propValue;try {propValue = getPropertyValue(getterTokens);}catch (NotReadablePropertyException ex) {throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,"Cannot access indexed value in property referenced " +"in indexed property path '" + propertyName + "'", ex);}// Set value for last key.String key = tokens.keys[tokens.keys.length - 1];if (propValue == null) {// null map value caseif (isAutoGrowNestedPaths()) {// TODO: cleanup, this is pretty hackyint lastKeyIndex = tokens.canonicalName.lastIndexOf('[');getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);propValue = setDefaultValue(getterTokens);}else {throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,"Cannot access indexed value in property referenced " +"in indexed property path '" + propertyName + "': returned null");}}if (propValue.getClass().isArray()) {PropertyHandler ph = getLocalPropertyHandler(actualName);Class<?> requiredType = propValue.getClass().getComponentType();int arrayIndex = Integer.parseInt(key);Object oldValue = null;try {if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {oldValue = Array.get(propValue, arrayIndex);}Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),requiredType, ph.nested(tokens.keys.length));int length = Array.getLength(propValue);if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {Class<?> componentType = propValue.getClass().getComponentType();Object newArray = Array.newInstance(componentType, arrayIndex + 1);System.arraycopy(propValue, 0, newArray, 0, length);setPropertyValue(actualName, newArray);propValue = getPropertyValue(actualName);}Array.set(propValue, arrayIndex, convertedValue);}catch (IndexOutOfBoundsException ex) {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Invalid array index in property path '" + propertyName + "'", ex);}}else if (propValue instanceof List) {PropertyHandler ph = getPropertyHandler(actualName);Class<?> requiredType = ph.getCollectionType(tokens.keys.length);List<Object> list = (List<Object>) propValue;int index = Integer.parseInt(key);Object oldValue = null;if (isExtractOldValueForEditor() && index < list.size()) {oldValue = list.get(index);}Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),requiredType, ph.nested(tokens.keys.length));int size = list.size();if (index >= size && index < this.autoGrowCollectionLimit) {for (int i = size; i < index; i++) {try {list.add(null);}catch (NullPointerException ex) {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Cannot set element with index " + index + " in List of size " +size + ", accessed using property path '" + propertyName +"': List does not support filling up gaps with null elements");}}list.add(convertedValue);}else {try {list.set(index, convertedValue);}catch (IndexOutOfBoundsException ex) {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Invalid list index in property path '" + propertyName + "'", ex);}}}else if (propValue instanceof Map) {PropertyHandler ph = getLocalPropertyHandler(actualName);Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);Map<Object, Object> map = (Map<Object, Object>) propValue;// IMPORTANT: Do not pass full property name in here - property editors// must not kick in for map keys but rather only for map values.TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);Object oldValue = null;if (isExtractOldValueForEditor()) {oldValue = map.get(convertedMapKey);}// Pass full property name and old value in here, since we want full// conversion ability for map values.Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(),mapValueType, ph.nested(tokens.keys.length));map.put(convertedMapKey, convertedMapValue);}else {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Property referenced in indexed property path '" + propertyName +"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");}}else {PropertyHandler ph = getLocalPropertyHandler(actualName);if (ph == null || !ph.isWritable()) {if (pv.isOptional()) {if (logger.isDebugEnabled()) {logger.debug("Ignoring optional value for property '" + actualName +"' - property not found on bean class [" + getRootClass().getName() + "]");}return;}else {throw createNotWritablePropertyException(propertyName);}}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) {if (ex instanceof PrivilegedActionException) {ex = ((PrivilegedActionException) ex).getException();}if (logger.isDebugEnabled()) {logger.debug("Could not read previous value of property '" +this.nestedPath + propertyName + "'", ex);}}}valueToApply = convertForProperty(propertyName, oldValue, originalValue, ph.toTypeDescriptor());}pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);}ph.setValue(this.wrappedObject, valueToApply);}catch (TypeMismatchException ex) {throw ex;}catch (InvocationTargetException ex) {PropertyChangeEvent propertyChangeEvent =new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, 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 methodscause = cause.getCause();}throw new MethodInvocationException(propertyChangeEvent, cause);}}catch (Exception ex) {PropertyChangeEvent pce =new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());throw new MethodInvocationException(pce, ex);}}}

现在通过PropertyHandler这个类的封装将反射操作都内聚了.