在上篇文章中我们了解到了如何设置Bean之间的依赖关系,以及如何将一个Bean设置到它所依赖的另一个bean的属性中,但是我们还忘了一步,就是对BeanDefinition进行解析,在Spring中是通过BeanDefinitionResolver来对BeanDefinition进行解析的。
在populateBean()会创建一个BeanDefinitionValueResolver对象,然后调用BeanDefinitionValueResolver#resolveValueNecessary方法来对BeanDefinition进行解析,根本上其实是对一个propertyValue进行解析。
/**
* Given a PropertyValue, return a value, resolving any references to other
* beans in the factory if necessary.
给定一个PropertyValue,返回一个值,如果有必要,解析对工厂中其他bean的任何引用
The value could be:
这个value可以是
* <li>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.
BeanDefinition,它导致创建相应的新bean实例。 Singleton标志和这种“内部bean”的名称总是被忽略:内部bean是匿名原型。
* <li>A RuntimeBeanReference, which must be resolved.
一个RuntimeBeanReference,必须解析
* <li>A ManagedList. This is a special collection that may contain
* RuntimeBeanReferences or Collections that will need to be resolved.
一个managedList,这是一个特殊的集合,可能包含需要解析的RuntimeBeanReference或者Collections
* <li>A ManagedSet. May also contain RuntimeBeanReferences or
* Collections that will need to be resolved.
一个ManagedSet。也可能包含RunTimeBeanReference或需要解决的集合
一个ManagedSet,
* <li>A ManagedMap. In this case the value may be a RuntimeBeanReference
* or Collection that will need to be resolved.
一个ManagedMap.在这种情况下,该值可能是需要解析的RunTimeBeanReference或Collection
* <li>An ordinary object or {@code null}, in which case it's left alone.
一个普通的对象或{@Code null},在这种情况下,它是独立的。
* @param argName the name of the argument that the value is defined for
为其定义值的参数的名称
* @param value the value object to resolve
要解析值的对象
* @return the resolved object
已经解析完成的对象
*/
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
我们必须检查每个值以查看它是否需要运行时引用,以及另一个要解析的bean
if (value instanceof RuntimeBeanReference) {
如果value是RuntimeBeanReference的实例,也就是说我们在定义的BeanDefinition的时候需要依赖其他bean,但是在解析阶段没有其他BeanFactory中并没有我们所需要的bean,所以需要将这个被依赖的bean表示成RuntimeBeanReference对象,在创建bean的时候将依赖解析成真正的Spring中存在的bean
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value instanceof RuntimeBeanNameReference) {
value是RuntimeBeanNameReference的实例,不可变占位符,用于属性值对象,当它是对工厂中另一个bean名称的引用时,在运行时解析
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;
}
else if (value instanceof BeanDefinitionHolder) {
包含带有名称和别名的BeanDefinition
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
解析BeanDefinition,不包含名称:使用虚拟名称
BeanDefinition 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);
}
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
可能需要解析运行时引用
return resolveManagedList(argName, (List<?>) value);
}
else if (value instanceof ManagedSet) {
// May need to resolve contained runtime references.
同上,set类型
return resolveManagedSet(argName, (Set<?>) value);
}
else if (value instanceof ManagedMap) {
// May need to resolve contained runtime references.
同上map类型
return resolveManagedMap(argName, (Map<?, ?>) value);
}
else if (value instanceof ManagedProperties) {
引用类型
Properties original = (Properties) value;
Properties copy = new Properties();
original.forEach((propKey, propValue) -> {
if (propKey instanceof TypedStringValue) {
propKey = evaluate((TypedStringValue) propKey);
}
if (propValue instanceof TypedStringValue) {
propValue = evaluate((TypedStringValue) propValue);
}
if (propKey == null || propValue == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error converting Properties key/value pair for " + argName + ": resolved to null");
}
copy.put(propKey, propValue);
});
return copy;
}
else if (value instanceof TypedStringValue) {
// Convert value to target type here.
将value转换成目标类型
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 if (value instanceof NullBean) {
return null;
}
else {
return evaluate(value);
}
}
上面这个方法就是对BeanDefinition中的PropertyValu进行解析,由于我们在解析的过程中所依赖的bean都没有进行创建,所以需要使用RuntimeBeanReference对象,值得注意的一点的是,在对集合类型进行解析的过程中,采用递归的方式重新调用resolveValueIfNecessary方法,因为在集合中的元素也需要进行解析。
在所有的属性都已经解析完成之后,我们就已经为依赖注入准备好了条件,这是真正把bean对象设置到它所依赖的另一个bean的属性中去的地方,其处理的属性是各种各样的。具体的依赖注入发生在BeanWrapper#setPropertyValues中实现,完成在BeanWrapperImpl中实现
总结:
在Bean的创建和对象的依赖注入的过程中,需要依据BeanDefinition中的信息来递归的完成依赖注入,在这个过程中我们可以发现有两个递归过程,这两个递归过程都是以getBean为入口的,有一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个是在依赖注入的过程中,通过递归调用容器的getBean的方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。同时在对Bean属性进行依赖注入的过程其实也是一个递归的过程。这样我们就可以一层一层的完成Bean的创建和注入了。