摘要
上一篇博客 spring IOC 依赖注入,看到了整个实例化Bean的过程,通过反射或者cglib增强实例化Bean。但此时对bean之间的依赖关系,属性的处理还未发生。这些将在populateBean中实现。
本文概述
依赖关系处理处理的依据是BeanDefinition
正文
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
//从BeanDefinition中获得属性值。
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!((PropertyValues)pvs).isEmpty()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
} else {
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var6 = this.getBeanPostProcessors().iterator();
while(var6.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var6.next();
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//对自动装配的注入
if (continueWithPropertyPopulation) {
if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
if (mbd.getResolvedAutowireMode() == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
if (mbd.getResolvedAutowireMode() == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
Iterator var9 = this.getBeanPostProcessors().iterator();
while(var9.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var9.next();
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
}
}
//对属性的注入
this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs != null && !pvs.isEmpty()) {
MutablePropertyValues mpvs = null;
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
}
List original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues)pvs;
if (mpvs.isConverted()) {
try {
bw.setPropertyValues(mpvs);
return;
} catch (BeansException var18) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
}
}
original = mpvs.getPropertyValueList();
} else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = this.getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
List<PropertyValue> deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
Iterator var11 = original.iterator();
while(true) {
while(var11.hasNext()) {
PropertyValue pv = (PropertyValue)var11.next();
if (pv.isConverted()) {
deepCopy.add(pv);
} else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
//对BeanDefinition的解析
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
}
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();
}
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
return;
} catch (BeansException var19) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
}
}
}
}
valueResolver.resolveValueIfNecessary(pv, originalValue)中完成了各种解析
public Object resolveValueIfNecessary(Object argName, Object value) {
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference)value;
return this.resolveReference(argName, ref);
} else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference)value).getBeanName();
refName = String.valueOf(this.doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);
} else {
return refName;
}
} else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder)value;
return this.resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
} else if (value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition)value;
String innerBeanName = "(inner bean)#" + ObjectUtils.getIdentityHexString(bd);
return this.resolveInnerBean(argName, innerBeanName, bd);
} else if (value instanceof ManagedArray) {
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 var9) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, var9);
}
} else {
elementType = Object.class;
}
}
return this.resolveManagedArray(argName, (List)value, elementType);
} else if (value instanceof ManagedList) {
return this.resolveManagedList(argName, (List)value);
} else if (value instanceof ManagedSet) {
return this.resolveManagedSet(argName, (Set)value);
} else if (value instanceof ManagedMap) {
return this.resolveManagedMap(argName, (Map)value);
} else if (value instanceof ManagedProperties) {
Properties original = (Properties)value;
Properties copy = new Properties();
Object propKey;
Object propValue;
for(Iterator var19 = original.entrySet().iterator(); var19.hasNext(); copy.put(propKey, propValue)) {
Entry<Object, Object> propEntry = (Entry)var19.next();
propKey = propEntry.getKey();
propValue = propEntry.getValue();
if (propKey instanceof TypedStringValue) {
propKey = this.evaluate((TypedStringValue)propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = this.evaluate((TypedStringValue)propValue);
}
}
return copy;
} else if (value instanceof TypedStringValue) {
TypedStringValue typedStringValue = (TypedStringValue)value;
Object valueObject = this.evaluate(typedStringValue);
try {
Class<?> resolvedTargetType = this.resolveTargetType(typedStringValue);
return resolvedTargetType != null ? this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType) : valueObject;
} catch (Throwable var10) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, var10);
}
} else {
return this.evaluate(value);
}
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
String refName = ref.getBeanName();
refName = String.valueOf(this.doEvaluate(refName));
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available");
} else {
//如果ref在双亲ioc容器中,这触发对ioc双亲容器的getBean
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
} else {
Object bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
} catch (BeansException var5) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var5);
}
}
在完成解析后为依赖注入做好了准备
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException {
List<PropertyAccessException> propertyAccessExceptions = null;
List<PropertyValue> propertyValues = pvs instanceof MutablePropertyValues ? ((MutablePropertyValues)pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues());
Iterator var6 = propertyValues.iterator();
while(var6.hasNext()) {
PropertyValue pv = (PropertyValue)var6.next();
try {
this.setPropertyValue(pv);
} catch (NotWritablePropertyException var9) {
if (!ignoreUnknown) {
throw var9;
}
} catch (NullValueInNestedPathException var10) {
if (!ignoreInvalid) {
throw var10;
}
} catch (PropertyAccessException var11) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList();
}
propertyAccessExceptions.add(var11);
}
}
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray = (PropertyAccessException[])propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
throw new PropertyBatchUpdateException(paeArray);
}
}
this.setPropertyValue(pv);
public void setPropertyValue(PropertyValue pv) throws BeansException {
AbstractNestablePropertyAccessor.PropertyTokenHolder tokens = (AbstractNestablePropertyAccessor.PropertyTokenHolder)pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = this.getPropertyAccessorForPropertyPath(propertyName);
} catch (NotReadablePropertyException var6) {
throw new NotWritablePropertyException(this.getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", var6);
}
tokens = this.getPropertyNameTokens(this.getFinalPath(nestedPa, propertyName));
if (nestedPa == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
nestedPa.setPropertyValue(tokens, pv);
} else {
this.setPropertyValue(tokens, pv);
}
}
propValue = this.getPropertyValue(getterTokens); 循环取得各种类型对象的引用
protected Object getPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens) throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
AbstractNestablePropertyAccessor.PropertyHandler ph = this.getLocalPropertyHandler(actualName);
if (ph != null && ph.isReadable()) {
try {
Object value = ph.getValue();
if (tokens.keys != null) {
if (value == null) {
if (!this.isAutoGrowNestedPaths()) {
throw new NullValueInNestedPathException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value of property referenced in indexed property path '" + propertyName + "': returned null");
}
value = this.setDefaultValue(tokens.actualName);
}
String indexedPropertyName = tokens.actualName;
for(int i = 0; i < tokens.keys.length; ++i) {
String key = tokens.keys[i];
if (value == null) {
throw new NullValueInNestedPathException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value of property referenced in indexed property path '" + propertyName + "': returned null");
}
int index;
if (value.getClass().isArray()) {
index = Integer.parseInt(key);
value = this.growArrayIfNecessary(value, index, indexedPropertyName);
value = Array.get(value, index);
} else if (value instanceof List) {
index = Integer.parseInt(key);
List<Object> list = (List)value;
this.growCollectionIfNecessary(list, index, indexedPropertyName, ph, i + 1);
value = list.get(index);
} else if (value instanceof Set) {
Set<Object> set = (Set)value;
int index = Integer.parseInt(key);
if (index < 0 || index >= set.size()) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Cannot get element with index " + index + " from Set of size " + set.size() + ", accessed using property path '" + propertyName + "'");
}
Iterator<Object> it = set.iterator();
for(int j = 0; it.hasNext(); ++j) {
Object elem = it.next();
if (j == index) {
value = elem;
break;
}
}
} else {
if (!(value instanceof Map)) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Property referenced in indexed property path '" + propertyName + "' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]");
}
Map<Object, Object> map = (Map)value;
Class<?> mapKeyType = ph.getResolvableType().getNested(i + 1).asMap().resolveGeneric(new int[]{0});
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
Object convertedMapKey = this.convertIfNecessary((String)null, (Object)null, key, mapKeyType, typeDescriptor);
value = map.get(convertedMapKey);
}
indexedPropertyName = indexedPropertyName + "[" + key + "]";
}
}
return value;
} catch (IndexOutOfBoundsException var14) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Index of out of bounds in property path '" + propertyName + "'", var14);
} catch (NumberFormatException var15) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid index in property path '" + propertyName + "'", var15);
} catch (TypeMismatchException var16) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid index in property path '" + propertyName + "'", var16);
} catch (InvocationTargetException var17) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Getter for property '" + actualName + "' threw exception", var17);
} catch (Exception var18) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Illegal attempt to get property '" + actualName + "' threw exception", var18);
}
} else {
throw new NotReadablePropertyException(this.getRootClass(), this.nestedPath + propertyName);
}
}
判断取得的引用是什么类型,并注入到其中
private void processKeyedProperty(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens, PropertyValue pv) {
Object propValue = this.getPropertyHoldingValue(tokens);
String lastKey = tokens.keys[tokens.keys.length - 1];
AbstractNestablePropertyAccessor.PropertyHandler ph;
Class requiredType;
Object convertedValue;
Object newArray;
if (propValue.getClass().isArray()) {
ph = this.getLocalPropertyHandler(tokens.actualName);
requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
Object oldValue = null;
try {
if (this.isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
convertedValue = this.convertIfNecessary(tokens.canonicalName, 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();
newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
this.setPropertyValue(tokens.actualName, newArray);
propValue = this.getPropertyValue(tokens.actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
} catch (IndexOutOfBoundsException var16) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + tokens.canonicalName, "Invalid array index in property path '" + tokens.canonicalName + "'", var16);
}
} else {
Object convertedValue;
if (propValue instanceof List) {
ph = this.getPropertyHandler(tokens.actualName);
requiredType = ph.getCollectionType(tokens.keys.length);
List<Object> list = (List)propValue;
int index = Integer.parseInt(lastKey);
convertedValue = null;
if (this.isExtractOldValueForEditor() && index < list.size()) {
convertedValue = list.get(index);
}
convertedValue = this.convertIfNecessary(tokens.canonicalName, convertedValue, 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((Object)null);
} catch (NullPointerException var15) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + tokens.canonicalName, "Cannot set element with index " + index + " in List of size " + size + ", accessed using property path '" + tokens.canonicalName + "': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
} else {
try {
list.set(index, convertedValue);
} catch (IndexOutOfBoundsException var14) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + tokens.canonicalName, "Invalid list index in property path '" + tokens.canonicalName + "'", var14);
}
}
} else {
if (!(propValue instanceof Map)) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + tokens.canonicalName, "Property referenced in indexed property path '" + tokens.canonicalName + "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
ph = this.getLocalPropertyHandler(tokens.actualName);
requiredType = ph.getMapKeyType(tokens.keys.length);
Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
Map<Object, Object> map = (Map)propValue;
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(requiredType);
convertedValue = this.convertIfNecessary((String)null, (Object)null, lastKey, requiredType, typeDescriptor);
Object oldValue = null;
if (this.isExtractOldValueForEditor()) {
oldValue = map.get(convertedValue);
}
newArray = this.convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(), mapValueType, ph.nested(tokens.keys.length));
map.put(convertedValue, newArray);
}
}
}
到此,依赖注入完成