主代码
对Bean属性原始值的解析过程在BeanDefinitionValueResolver类中的resolveValueIfNecessary方法中,BeanDefinitionValueResolver主要是用于将bean定义对象中包含的值解析为应用于目标bean实例的实际值。
public Object resolveValueIfNecessary(Object argName, Object value) {
if (value instanceof RuntimeBeanReference) {
// 1. RuntimeBeanReference类型
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
} else if (value instanceof RuntimeBeanNameReference) {
// 2. RuntimeBeanNameReference类型
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
// 抛出异常
}
return refName;
} else if (value instanceof BeanDefinitionHolder) {
// 3. BeanDefinitionHolder类型
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
} else if (value instanceof BeanDefinition) {
// 4. 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) {
// 5.ManagedArray类型
ManagedArray array = (ManagedArray) value;
// 运行时解析的元素类型
Class<?> elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
} else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
} else if (value instanceof ManagedList) {
// 6.ManagedList类型
return resolveManagedList(argName, (List<?>) value);
} else if (value instanceof ManagedSet) {
// 7.ManagedSet类型
return resolveManagedSet(argName, (Set<?>) value);
} else if (value instanceof ManagedMap) {
// 8.ManagedMap类型
return resolveManagedMap(argName, (Map<?, ?>) value);
} else if (value instanceof ManagedProperties) {
// 9.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);
} // for
return copy;
} else if (value instanceof TypedStringValue) {
// 10.TypedStringValue类型
TypedStringValue typedStringValue = (TypedStringValue) value;
// 解析value
Object valueObject = evaluate(typedStringValue);
// 解析typedStringValue的类型
Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
if (resolvedTargetType != null) {
// 若从typedStringValue内部解析出类型,则使用转换器进行类型转换
return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
} else {
// 若没有解析出类型,直接返回
return valueObject;
}
} else {
// 其他情况
return evaluate(value);
}
}
1. RuntimeBeanReference类型
- 用途
RuntimeBeanReference:当属性值对象是工厂中另一个bean的引用时,使用不可变的占位符类,在运行时进行解析。
<bean class="foo.bar.xxx">
<property name="referBeanName" ref="otherBeanName" />
</bean>
解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中,即
reference = new RuntimeBeanReference("otherBeanName");
xxxBeanDefinition.getPropertyValues().addPropertyValue("referBeanName", reference);
- 转换过程
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
// 获取该Bean引用名称,如上例“otherBeanName”
String refName = ref.getBeanName();
// 若refName是SPEL表达式,需要解析
refName = String.valueOf(doEvaluate(refName));
if (ref.isToParent()) {
// 若显式引用父工厂中的bean
if (this.beanFactory.getParentBeanFactory() == null) {
// 抛出异常:显式引用父工厂中的bean但父工厂bean不存在
}
return this.beanFactory.getParentBeanFactory().getBean(refName);
} else {
// 获取该引用Bean
Object bean = this.beanFactory.getBean(refName);
// 注册依赖的Bean(this.beanName依赖refName)
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
}
private Object doEvaluate(String value) {
// beanFactory来解析
return this.beanFactory.evaluateBeanDefinitionString(value, this.beanDefinition);
}
再看AbstractBeanFactory对该表达式的解析,首先会判断是否存在语言解析器,如果存在则调用语言解析器(ExpressionParser)的方法进行解析(应用语言解析器的调用主要是在解析依赖注入bean的时候,以及在完成bean的初始化和属性获取后进行属性填充的时候)。
protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition){
if (this.beanExpressionResolver == null) {
return value;
}
// 获取该beanDefinition的Scope(可能为prototype、singleton、request等等)
Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}
2. RuntimeBeanNameReference类型
代码中直接返回了refName,而非其指向的Bean实例,RuntimeBeanNameReference没有弄明白,可讨论
3. BeanDefinitionHolder类型
- 用途:
具有名称和别名的bean定义的持有者,可以注册为内部bean的占位符。源码:
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
@Nullable
private final String[] aliases;
}
- 转换过程
private Object resolveInnerBean(Object argName, String innerBeanName, BeanDefinition innerBd) {
RootBeanDefinition mbd = null;
// 获取合并BeanDefinition
mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
String actualInnerBeanName = innerBeanName;
if (mbd.isSingleton()) {
// 若是单例,则生成唯一的Bean名称(增加计数器直到名称是唯一的)
actualInnerBeanName = adaptInnerBeanName(innerBeanName);
}
// 注册内部bean与包含该bean的bean的关系
this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
// 确保内部bean所依赖的bean的初始化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
this.beanFactory.getBean(dependsOnBean);
}
}
// 开始创建内部bean
Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
if (innerBean instanceof FactoryBean) {
// 若是工厂Bean,调用getObject方法生成Bean,并返回
boolean synthetic = mbd.isSynthetic();
return this.beanFactory.getObjectFromFactoryBean((FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
} else {
return innerBean;
}
}
4. BeanDefinition类型
- 用途
匿名bean,就是没有名称(id)的bean,不能被其他bean用名称获取到,只能通过autowire=”byType”方式获取;如果有某个类,不想被其他类通过任何方式获取,只为某个类提供服务,则需要采用内部匿名类,用法如下:
<bean id="myStudent" class="com.hk.spring.di10.Student" autowire="byType">
<property name="name" value="张三"/>
<property name="age" value="9"/>
<property name="school">
<!-- 内部匿名bean -->
<bean class="com.hk.spring.di10.School">
<property name="schloolName" value="红林小学"/>
</bean>
- 转换过程
代码中可以看出,该内部Bean的名称是自动生成的且唯一的,转换过程类似于BeanDefinitionHolder类型的转换。
5. ManagedArray类型
- 用途
用于保存托管数组元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象),源码:
public class ManagedArray extends ManagedList<Object> {
// 目标数组创建运行时的解析的元素类型
volatile Class<?> resolvedElementType;
//......
}
//用于保存托管列表元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)
public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetadataElement {
@Nullable
private Object source;
@Nullable
private String elementTypeName;
// 该集合是否允许合并另一个集合的元素
private boolean mergeEnabled;
}
- 转换过程
private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
// 解析并转换每一个元素
Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
6. ManagedList类型
- 用途
用于保存托管列表元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)
- 转换过程
private List<?> resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
for (int i = 0; i < ml.size(); i++) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
}
return resolved;
}
7. ManagedSet类型
- 用途
用于保存托管Set值的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)
public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMetadataElement {
private Object source;
private String elementTypeName;
private boolean mergeEnabled;
}
- 转换过程
private Set<?> resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
int i = 0;
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
i++;
}
return resolved;
}
8. ManagedMap类型
- 用途
用于保存托管map值的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)
public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable, BeanMetadataElement {
private Object source;
private String keyTypeName;
private String valueTypeName;
private boolean mergeEnabled;
}
- 转换过程
private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());
for (Map.Entry<?, ?> entry : mm.entrySet()) {
// 解析key
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
// 解析value
Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, entry.getKey()), entry.getValue());
resolved.put(resolvedKey, resolvedValue);
}
return resolved;
}
9. ManagedProperties类型
- 用途
spring管理的Properties实例,该实例支持父/子定义的合并。
public class ManagedProperties extends Properties implements Mergeable, BeanMetadataElement {
private Object source;
private boolean mergeEnabled;
//......
}
- 转换过程
protected Object evaluate(TypedStringValue value) {
// 若有必要,则使用SPEL解析器进行解析
Object result = doEvaluate(value.getValue());
if (!ObjectUtils.nullSafeEquals(result, value.getValue())) {
// 若解析后的与原来的值不相等,设置该value是动态的
value.setDynamic();
}
return result;
}
10.TypedStringValue类型
- 用途
类型字符串值的容器。可以添加到bean定义中,以便为字符串值(例如集合元素)显式指定目标类型。
public class TypedStringValue implements BeanMetadataElement {
@Nullable
private String value;
@Nullable
private volatile Object targetType;
@Nullable
private Object source;
@Nullable
private String specifiedTypeName;
private volatile boolean dynamic;
//......
}
11. 其他情况
protected Object evaluate(Object value) {
if (value instanceof String) {
// 字符串(最后会使用SPEL解析器进行解析)
return doEvaluate((String) value);
} else if (value instanceof String[]) {
// 字符串数组
String[] values = (String[]) value;
boolean actuallyResolved = false;
Object[] resolvedValues = new Object[values.length];
for (int i = 0; i < values.length; i++) {
String originalValue = values[i];
// 每一个元素进行解析
Object resolvedValue = doEvaluate(originalValue);
if (resolvedValue != originalValue) {
actuallyResolved = true;
}
resolvedValues[i] = resolvedValue;
}
return (actuallyResolved ? resolvedValues : values);
} else {
// 即不是字符串,也不是字符数组
return value;
}
}