前面文章中对依赖注入的触发和bean的创建做了学习记录,本文将来记录一下bean的属性注入过程。Bean的属性注入发生在 BeanDefinitionValueResolver
这个类中, BeanDefinitionValueResolver
这类是用于bean工厂实现的Helper类,职责就是将bean定义对象中包含的值解析为应用于目标bean实例的实际值。
BeanDefinitionValueResolver
类中的 resolveValueIfNecessary()
方法包含了对所有注入类型的处理。所以本文主要围绕这个方法展开来说。
resolveValueIfNecessary()
:给定一个PropertyValue,返回一个value,解析对工厂中其他bean的引用。 value可能是:
argName :为其定义的参数的名称
value :要解析的值对象
public Object resolveValueIfNecessary(Object argName, Object value)
当在beanfactory中作为另外一个 bean的引用时 ,作为属性值对象,将在运行时进行解析。 RuntimeBeanReference是在对BeanDefinition进行解析时生成的数据对象。
if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); }
当在beanfactory中作为另外一个 bean名称的引用时 ,作为属性值对象,将在运行时进行解析。
else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (!this.beanFactory.containsBean(refName)) { //异常:Invalid bean name '" + refName + "' in bean reference for " + argName } return refName; }
解析BeanDefinitionHolder:包含具有名称和别名的BeanDefinition。BeanDefinitionHolder就是使用名称或者别名来保存BeanDefinition的。
else if (value instanceof BeanDefinitionHolder) { BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); }
解析纯粹的BeanDefinition
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); }
包含运行时期的bean引用(将被解析为bean对象)
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. //异常:Error resolving array type for " + argName } } else { elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); }
包含运行时期的bean引用(将被解析为bean对象)
//对ManagedList进行解析 else if (value instanceof ManagedList) { return resolveManagedList(argName, (List<?>) value); } //对ManagedSet进行解析 else if (value instanceof ManagedSet) { return resolveManagedSet(argName, (Set<?>) value); } //对ManagedMap进行解析 else if (value instanceof ManagedMap) { return resolveManagedMap(argName, (Map<?, ?>) value); }
ManagedProperties表示的是一个spring管理的属性实例,它支持父/子 definition的合并。
//对ManagedProperties进行解析 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; }
TypedStringValue保存的是一个类型的属性值。
//对TypedStringValue进行解析 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( //异常:Error converting typed String value for " + argName } }
将给定的值作为表达式进行评估。
else { return evaluate(value); }
在完成上述解析之后,已经为我们的依赖注入做好了准备。这是真正把Bean对象设置到它所依赖的另一个Bean的属性中去的地方,可以看到,处理的属性也是各式各样的。具体属性的注入是在之前提到的BeanWrapper接口的实现类BeanWrapperImpl的setPropertyValue方法来完成。
这个方法是私有的,是BeanWrapperImpl实际处理的方法,其对外也提供了setPropertyValue的其它重载方法来提供服务。
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException
PropertyTokenHolder是BeanWrapperImpl的内部类:
private static class PropertyTokenHolder { public String canonicalName; public String actualName; public String[] keys; }
在setPropertyValue方法中会根据tokens变量是否为null,有两个不同的分支。其中当tokens为null时,则会对属性名进行递归调用分析处理,返回分析处理后的BeanWrapImpl对象nestedBw。如果nestedBw==this,则会设置pv的resolvedTokens属性值,最后将调用nestedBw对象的设置属性值方法设置属性。来具体看看:
// 设置tokens的索引和keys 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; //getPropertyValue用来获取Bean中对对象注入的引用; try { propValue = getPropertyValue(getterTokens); } catch (NotReadablePropertyException ex) { //异常:Cannot access indexed value in property referenced " + "in indexed property path '" + propertyName }
if (propValue == null) { // 空值映射的情况 if (this.autoGrowNestedPaths) { // TODO: cleanup, this is pretty hacky int lastKeyIndex = tokens.canonicalName.lastIndexOf('['); getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex); propValue = setDefaultValue(getterTokens); } else { //异常: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)); Array.set(propValue, arrayIndex, convertedValue); } catch (IndexOutOfBoundsException ex) { //异常:Invalid array index in property path '" + propertyName } }
else if (propValue instanceof List) { PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName); Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType( pd.getReadMethod(), tokens.keys.length); List list = (List) 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) { //异常:InvalidPropertyException } } list.add(convertedValue); } else { try { list.set(index, convertedValue); } catch (IndexOutOfBoundsException ex) { //异常:Invalid list index in property path '" + propertyName + "'" } } }
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 map = (Map) propValue; //重要提示:不要在这里传递完整的属性名称 TypeDescriptor typeDescriptor = (mapKeyType != null ? TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class)); Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor); Object oldValue = null; if (isExtractOldValueForEditor()) { oldValue = map.get(convertedMapKey); } // 在这里传递完整的属性名称和旧值,因为希望对map值有完整的转换能力。 Object convertedMapValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(property(pd), tokens.keys.length)); map.put(convertedMapKey, convertedMapValue); }
这里是核心的地方,取得注入属性的set方法,通过反射机制,把对象注入进去。
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() : pd.getWriteMethod());
通过上面的几篇分析我们大概的熟悉了Bean创建和对象依赖注入的一个过程,在这个过程中,spring需要根据Beandefinition中的信息来递归完成依赖注入。并且这些递归的入口都是getBean这个方法。
一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用;
另一个递归是在依赖注入时通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。
在对Bean的属性进行依赖注入时解析的过程也是一个递归的过程。这样就可以根据依赖关系,一层一层的完成Bean的创建和注入,直到最后完成当前Bean的创建。
《Spring技术内幕》
https://www.cnblogs.com/davidwang456/p/4213652.html