4 IoC容器的依赖注入(2)

来源:互联网 发布:最近网络最流行的话 编辑:程序博客网 时间:2024/06/05 13:23

相对于Bean的创建过程,注入过程显得简单而清晰的多。

注入的过程整体分为两个阶段:

第一个阶段是依据BeanDefition定义的property找到相关的属性值,这个过程中如果定义了autowireByName 或者autowireByType  优先进行这两个定义的查找,然后进行正常匹配,也就是我们定义的<property>,这个部分会覆盖掉autowire的内容。以上所有找到的属性值都会放到一个deepcopy容器里面。

第二个阶段就是把deepcopy容器的值注入到bean中。

1  populateBean 依赖注入的入口

在这个方法中注册了后处理方法,并且完成了autowire定义的属性值的获取。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {//获得所有的属性集合PropertyValues pvs = mbd.getPropertyValues();if (bw == null) {if (!pvs.isEmpty()) {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.boolean continueWithPropertyPopulation = true;//注册后处理方法if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}if (!continueWithPropertyPopulation) {return;}//优先设置自动装配 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}//从自动装配方法中获得需要注入的属性  如果配置了普通的属性注入 这些值将会在后面被覆盖pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);//在这处理普通的依赖注入  会覆盖掉之前自动装配的结果if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvs == null) {return;}}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);}}//依赖注入的入口applyPropertyValues(beanName, mbd, bw, pvs);}

2  autowireByName

根据名字自动注入

protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);//遍历自动状态的名字  从当前的容器中寻找对应的Bean,如果能找到,就把这个值放入属性值容器中 用于后面的注入行为for (String propertyName : propertyNames) {if (containsBean(propertyName)) {Object bean = getBean(propertyName);pvs.add(propertyName, bean);registerDependentBean(propertyName, beanName);if (logger.isDebugEnabled()) {logger.debug("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");}}}}

3 autowireByType

根据类型自动注入,核心方法是doResolveDependency

protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);//Spring规定不能使用Object类型的 自动装配if (!Object.class.equals(pd.getPropertyType())) {MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());//构造一个autowirebyType的处理器,用于找到对应的注入的BeanDependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);// 处理自动装配 找到对应的属性值Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {registerDependentBean(autowiredBeanName, beanName);if (logger.isDebugEnabled()) {logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +propertyName + "' to bean named '" + autowiredBeanName + "'");}}autowiredBeanNames.clear();}}catch (BeansException ex) {throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);}}}

4 doResolveDependency

这个方法处理byType自动注入的值获取过程。分别处理了 array collection(list 和set) map等数组和集合类型的自动注入。对于这个注入过程,所有的集合和Map类型的set注入方法必须定义为接口类型,如果定义为他们的实现类,就无法完成注入

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {Class<?> type = descriptor.getDependencyType();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());return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}//对数组类型的自动注入if (type.isArray()) {Class<?> componentType = type.getComponentType();DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);targetDesc.increaseNestingLevel();Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc);if (matchingBeans.isEmpty()) {if (descriptor.isRequired()) {raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);}return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());Object result = converter.convertIfNecessary(matchingBeans.values(), type);if (getDependencyComparator() != null && result instanceof Object[]) {Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));}return result;}//对集合类型的注入  这里的集合对应的set方法必须定义为set list这样的接口类型// 如果定义为他们的实现类  将不能完成注入  // 对于集合的注入  spring将搜索配置文件中所有定义为集合泛型类型的bean 注入// 如果没有定义泛型  也不能完成注入else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {Class<?> elementType = descriptor.getCollectionType();if (elementType == null) {if (descriptor.isRequired()) {throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");}return null;}DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);targetDesc.increaseNestingLevel();Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc);if (matchingBeans.isEmpty()) {if (descriptor.isRequired()) {raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);}return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());Object result = converter.convertIfNecessary(matchingBeans.values(), type);if (getDependencyComparator() != null && result instanceof List) {Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));}return result;}//Map类型也必须定义为接口类型else if (Map.class.isAssignableFrom(type) && type.isInterface()) {Class<?> keyType = descriptor.getMapKeyType();if (keyType == null || !String.class.isAssignableFrom(keyType)) {if (descriptor.isRequired()) {throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +"] must be assignable to [java.lang.String]");}return null;}Class<?> valueType = descriptor.getMapValueType();if (valueType == null) {if (descriptor.isRequired()) {throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");}return null;}DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor);targetDesc.increaseNestingLevel();Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc);if (matchingBeans.isEmpty()) {if (descriptor.isRequired()) {raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);}return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}return matchingBeans;}// 对于其他类型else {//首先找到所有符合类型定义的BeanMap<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);//如果没有找到 并且这个属性还是required 抛出异常if (matchingBeans.isEmpty()) {if (descriptor.isRequired()) {raiseNoSuchBeanDefinitionException(type, "", descriptor);}return null;}//如果结果不唯一  查看有没有定义primary的  如果没有定义  抛出不唯一的异常if (matchingBeans.size() > 1) {String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (primaryBeanName == null) {throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());}if (autowiredBeanNames != null) {autowiredBeanNames.add(primaryBeanName);}return matchingBeans.get(primaryBeanName);}// 对于唯一的结果 放入属性集合Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();if (autowiredBeanNames != null) {autowiredBeanNames.add(entry.getKey());}return entry.getValue();}}

5 applyPropertyValues  获取属性值的过程

这个方法是获取属性值的主要方法  这里主要利用了BeanDefinitionValueResolver进行了属性值转换,将属性值与BeanDefition中定义的需要的值连接在一起,放入deepcopy容器中

/** * Apply the given property values, resolving any runtime references * to other beans in this bean factory. Must use deep copy, so we * don't permanently modify this property. * @param beanName the bean name passed for better exception information * @param mbd the merged bean definition * @param bw the BeanWrapper wrapping the target object * @param pvs the new property values */protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {if (pvs == null || pvs.isEmpty()) {return;}//MutablePropertyValues mpvs = null;//原始属性值List<PropertyValue> original;if (System.getSecurityManager() != null) {if (bw instanceof BeanWrapperImpl) {((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());}}if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;if (mpvs.isConverted()) {// Shortcut: use the pre-converted values as-is.try {bw.setPropertyValues(mpvs);return;}catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}}original = mpvs.getPropertyValueList();}else {original = Arrays.asList(pvs.getPropertyValues());}TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}//属性值转换器  需要将注入的属性值转换为beanDefition定义的属性值BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);// 建立一个属性值的深拷贝  保存所有转换过的属性值List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());boolean resolveNecessary = false;for (PropertyValue pv : original) {//如果已经处理过,直接放入list中if (pv.isConverted()) {deepCopy.add(pv);}else {String propertyName = pv.getName();Object originalValue = pv.getValue();//第一次转换Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);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.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();}// Set our (possibly massaged) deep copy.try {//将转换过的值注入到到Bean中bw.setPropertyValues(new MutablePropertyValues(deepCopy));}catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}}

6 resolveValueIfNecessary属性值转换器

这里根据不同类型的属性值的定义,分别去处理这个属性值

/*Given a PropertyValue, return a value, resolving any references to other beans in the factory if necessary. The value could be: A BeanDefinition, which leads to the creation of a corresponding new bean instance. Singleton flags and names of such "inner beans" are always ignored: Inner beans are anonymous prototypes. A RuntimeBeanReference, which must be resolved. A ManagedList. This is a special collection that may contain RuntimeBeanReferences or Collections that will need to be resolved. A ManagedSet. May also contain RuntimeBeanReferences or Collections that will need to be resolved. A ManagedMap. In this case the value may be a RuntimeBeanReference or Collection that will need to be resolved. An ordinary object or null, in which case it's left alone.*/public Object resolveValueIfNecessary(Object argName, Object value) {/**处理最常见的一类注入  注入的对象是容器中的另一个bean这里成为runtime reference */if (value instanceof RuntimeBeanReference) {RuntimeBeanReference ref = (RuntimeBeanReference) value;return resolveReference(argName, ref);}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;}/**下面两个都是在处理嵌套定义的bean*/else if (value instanceof BeanDefinitionHolder) {// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.//这里处理的是正式定义的bean 有idBeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());}else if (value instanceof BeanDefinition) {// Resolve plain BeanDefinition, without contained name: use dummy name.//这里处理的是匿名的beanBeanDefinition bd = (BeanDefinition) value;String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +ObjectUtils.getIdentityHexString(bd);return resolveInnerBean(argName, innerBeanName, bd);}//数组的处理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);}//对list的处理else if (value instanceof ManagedList) {// May need to resolve contained runtime references.return resolveManagedList(argName, (List<?>) value);}//对set的处理else if (value instanceof ManagedSet) {// May need to resolve contained runtime references.return resolveManagedSet(argName, (Set<?>) value);}//对map的处理else if (value instanceof ManagedMap) {// May need to resolve contained runtime references.return resolveManagedMap(argName, (Map<?, ?>) value);}//对property集合的处理  不需要转换  直接放入copy中else if (value instanceof ManagedProperties) {Properties original = (Properties) value;Properties copy = new Properties();for (Map.Entry<Object, Object> propEntry : original.entrySet()) {Object propKey = propEntry.getKey();Object propValue = propEntry.getValue();if (propKey instanceof TypedStringValue) {propKey = evaluate((TypedStringValue) propKey);}if (propValue instanceof TypedStringValue) {propValue = evaluate((TypedStringValue) propValue);}copy.put(propKey, propValue);}return copy;}/**对于其他常量的处理  String int boolean 等类型  对他们的处理不需要借助于额外的转换器 仅需调用evaluate生成对应值即可*///对String类型的处理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);}}//对于其他值的处理  else {return evaluate(value);}}

7 setPropertyValue 注入属性值的过程

这里主要是通过反射将前面得到的属性值注入到Bean中

private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {String propertyName = tokens.canonicalName;String actualName = tokens.actualName;/** 对 array   list  map  这三种类型的处理 这三种类型的注入并不是通过set方法的反射完成而是直接通过Java的对这些类的反射方法 直接修改对应属性值*/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()) {PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(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, TypeDescriptor.nested(property(pd), 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);}//通过Java 反射包下面Array类进行对应的值的修改Array.set(propValue, arrayIndex, convertedValue);}catch (IndexOutOfBoundsException ex) {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Invalid array index in property path '" + propertyName + "'", ex);}}//对list进行注入else if (propValue instanceof List) {PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);Class<?> requiredType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), 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, TypeDescriptor.nested(property(pd), 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进行赋值list.set(index, convertedValue);}catch (IndexOutOfBoundsException ex) {throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,"Invalid list index in property path '" + propertyName + "'", ex);}}}//对map进行注入else if (propValue instanceof Map) {PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), tokens.keys.length);Class<?> mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(pd.getReadMethod(), 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, TypeDescriptor.nested(property(pd), tokens.keys.length));//直接对获取到的map进行赋值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 [" + pv.getValue() + "]");}}//对于非集合类型的注入else {PropertyDescriptor pd = pv.resolvedDescriptor;if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);if (pd == null || pd.getWriteMethod() == null) {if (pv.isOptional()) {logger.debug("Ignoring optional value for property '" + actualName +"' - property not found on bean class [" + getRootClass().getName() + "]");return;}else {PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,matches.buildErrorMessage(), matches.getPossibleMatches());}}pv.getOriginalPropertyValue().resolvedDescriptor = pd;}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() && pd.getReadMethod() != null) {//通过反射获取对应的set方法final Method readMethod = pd.getReadMethod();if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&!readMethod.isAccessible()) {if (System.getSecurityManager()!= null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {//提升方法的访问权限  readMethod.setAccessible(true);return null;}});}else {readMethod.setAccessible(true);}}try {if (System.getSecurityManager() != null) {oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {//通过反射驱动set方法注入return readMethod.invoke(object);}}, acc);}else {oldValue = readMethod.invoke(object);}}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, new TypeDescriptor(property(pd)));}pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);}final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :pd.getWriteMethod());if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {if (System.getSecurityManager()!= null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {writeMethod.setAccessible(true);return null;}});}else {writeMethod.setAccessible(true);}}final Object value = valueToApply;if (System.getSecurityManager() != null) {try {AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {writeMethod.invoke(object, value);return null;}}, acc);}catch (PrivilegedActionException ex) {throw ex.getException();}}else {writeMethod.invoke(this.object, value);}}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, pd.getPropertyType(), ex.getTargetException());}else {throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());}}catch (Exception ex) {PropertyChangeEvent pce =new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());throw new MethodInvocationException(pce, ex);}}}

8 getReadMethod

 public synchronized Method getReadMethod() {Method readMethod = getReadMethod0();if (readMethod == null) {    Class cls = getClass0();    if (cls == null || (readMethodName == null && readMethodRef == null)) {// The read method was explicitly set to null.return null;    }    if (readMethodName == null) {Class type = getPropertyType0();if (type == boolean.class || type == null) {    readMethodName = "is" + getBaseName();//boolean类型 方法使用is开头} else {    readMethodName = "get" + getBaseName();//get方法}    }        // Since there can be multiple write methods but only one getter    // method, find the getter method first so that you know what the    // property type is.  For booleans, there can be "is" and "get"    // methods.  If an "is" method exists, this is the official    // reader method so look for this one first.    readMethod = Introspector.findMethod(cls, readMethodName, 0);    if (readMethod == null) {readMethodName = "get" + getBaseName();readMethod = Introspector.findMethod(cls, readMethodName, 0);    }    try {setReadMethod(readMethod);    } catch (IntrospectionException ex) {// fall    }}return readMethod;    }





0 0
原创粉丝点击