双十一过去了,终于可以把这篇博客补上了。
本文将分析BeanWrapperImpl,出现了大量的源码。如果你对BeanWrapper有相当的了解,请略过;如果想稍微了解一下BeanWrapper,可能需要关注一下源码。
--------------------------------------------
学习 Spring 核心是一件比较耗费精力的过程,代码太多,代码的层次也比较深。每次我都是在上午看代码,把一天中精力比较集中的时间段留给了他。在【Spring IOC -依赖注入(概述 getBean)】一文中,我们了解了 Spring 依赖注入的大概过程。本次我们要着重说明一下依赖注入中的 Bean 实例化,以及自动注入的实现方式。
1. 本次分享需要解决的几个问题
- 不得不说的 BeanWrapper
- 实例化的经过的各层传递
- 常用的自动注入如何实现
2. 不得不说的 BeanWrapper
BeanWrapper 是 Spring 框架中十分重要的技术支持组件。他的实现类大概有1千多行代码,很长,但是功能也是比较内聚的。BeanWrapper 的主要作用是把所有的 Bean 的属性都可以集中处理。这种集中处理的机制来自于 Java 的反射。通过 Java 的反射,可以把 Bean 的属性抽取出来,然后在通过反射的方式进行赋值。这种方式使 Spring 可以用同一种方式来处理 Bean 的属性。
2.1 BeanWrapper 的实现类图
上图中可以发现默认实现 BeanWrapper 的实现类 BeanWrapperImpl 通过继承 AbstractPropertyAccessor 来增强其属性的赋值功能。这个过程中你可以定义自己的类型处理器。在org.springframework.beans.propertyeditors包下面是 Spring 扩展自己定义的类型处理器,如果需要可以扩展自己处理器注册到容器中。这些不是这次讨论的主题,就不详细说明了。
2.2 构建 BeanWrapper 的实例
构建一个 BeanWrapper 实例有很多种方式,可以指定需要实例化的 Bean.class,可以指定需要包装的 Bean 实例等。下面就 BeanWrapper 的属性的进行说明。
Object object; | 被包装的Bean实例,如果传递了对应的 class,通过 BeanUtils 实例化一个 |
String nestedPath = ""; | 嵌套路径。例如如果BeanA里面包含属性BeanB,那么访问BeanA的BeanB属性的路径是“beanA.beanB”。那BeanB的嵌套路径就是“beanA.” |
Object rootObject; | 嵌套上级Bean实例,如果没有上级,就是自己本身 |
TypeConverterDelegate typeConverterDelegate; | 类型转换器代理实现 |
CachedIntrospectionResults cachedIntrospectionResults; | 缓存Bean实例对应的class、属性等信息(beanInfo),在使用的Bean的信息,可以从中获取。(Java 内省机制) |
Map<String, BeanWrapperImpl> nestedBeanWrappers; | 保存嵌套路径到BeanWrapper实例的映射关系保存。 |
构造方法重要的有两个:
/**
* Create new BeanWrapperImpl for the given object,
* registering a nested path that the object is in.
* @param object object wrapped by this BeanWrapper
* @param nestedPath the nested path of the object
* @param rootObject the root object at the top of the path
*/
public BeanWrapperImpl(Object object, String nestedPath, Object rootObject) {
registerDefaultEditors();
setWrappedInstance(object, nestedPath, rootObject);
}
/**
* Create new BeanWrapperImpl for the given object,
* registering a nested path that the object is in.
* @param object object wrapped by this BeanWrapper
* @param nestedPath the nested path of the object
* @param superBw the containing BeanWrapper (must not be <code>null</code>)
*/
private BeanWrapperImpl(Object object, String nestedPath, BeanWrapperImpl superBw) {
setWrappedInstance(object, nestedPath, superBw.getWrappedInstance());
setExtractOldValueForEditor(superBw.isExtractOldValueForEditor());
setAutoGrowNestedPaths(superBw.isAutoGrowNestedPaths());
setAutoGrowCollectionLimit(superBw.getAutoGrowCollectionLimit());
setConversionService(superBw.getConversionService());
setSecurityContext(superBw.acc);
}
/**
* Switch the target object, replacing the cached introspection results only
* if the class of the new object is different to that of the replaced object.
* @param object the new target object
* @param nestedPath the nested path of the object
* @param rootObject the root object at the top of the path
*/
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Bean object must not be null");
this.object = object;
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object);
this.nestedBeanWrappers = null;
this.typeConverterDelegate = new TypeConverterDelegate(this, object);
setIntrospectionClass(object.getClass());
}
2.3 使用 BeanWrapper 设置&获取属性值(包含嵌套)
- PropertyTokenHolder
在了解 BeanWrapper 设置和获取获取属性值前,我们先了解一下 PropertyTokenHolder。PropertyTokenHolder 是 BeanWrapperImpl 的内部类,他很简单,定义了属性命名描述。一个能标识 Bean 的唯一名称(可能包含嵌套的路径),Bean 真实名称(不包含嵌套路径),访问集合属性的索引数组。
private static class PropertyTokenHolder {
// 例如 BeanA 中有个 Set 属性,他们的名称是“xxxSet”,
// 我们可以通过“xxxSet[1]”访问这个属性值,需要获得BeanA.xxxSet的一个值
// 权威唯一名称,例如:xxxSet[1]
public String canonicalName;
// 真实名称,例如:xxxSet
public String actualName;
// 访问集合索引,例如:["1"]
public String[] keys;
}
- 设置属性值
设置属性值,设置属性值有两个重载的方法可供选择。在设置属性时,需要处理嵌套属性的设置。此种需要了解 PropertyTokenHolder,他是一个内部简单类,定义了嵌套的名称、真实名称、对应的访问KEY三个属性。
@Override
public void setPropertyValue(String propertyName, Object value) throws BeansException {
BeanWrapperImpl nestedBw;
try {
// 此方法在下面介绍
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
// getFinalPath 的处理逻辑是如果 nestedBw 是自己情况,直接返回传入的 propertyName
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
// 后面介绍这个方法
nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
// 如果无法获取属性标识,重新计算一下
if (tokens == null) {
String propertyName = pv.getName();
BeanWrapperImpl nestedBw;
try {
// 如果是嵌套的 BeanWrapper,获取的是嵌套的实例,否则是自己本身
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
if (nestedBw == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
nestedBw.setPropertyValue(tokens, pv);
}
else {
setPropertyValue(tokens, pv);
}
}
@SuppressWarnings("unchecked")
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
// 如果标识中的 keys 不为空,说明属性是集合方式的,需要通过集合的方式处理
// 并且应该提供对应属性的 getter 方法,因为需要访问对应的集合
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 case
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 {
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));
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 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) {
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.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 map = (Map) 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 = (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);
}
// 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.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() + "]");
}
}
// 当标识中Key为空,此时需要直接设定属性的值
else {
// 获取对应的属性描述
PropertyDescriptor pd = pv.resolvedDescriptor;
// 如果无法获取属性描述,或者获得的属性描述对应的 class 不是被包装实例的class时,重新获取
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 {
// 如果存在 getter,从 getter 中获取对应的属性值,为了某些个性化的编辑器使用
if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {
final Method readMethod = pd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&
!readMethod.isAccessible()) {
if (System.getSecurityManager()!= null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
}
else {
readMethod.setAccessible(true);
}
}
try {
if (System.getSecurityManager() != null) {
oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
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, pd);
}
pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
}
// 获取 setter 方法
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>() {
public 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>() {
public 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);
}
}
}
/**
* 通过嵌套的属性路径递归查询 BeanWrapper 实例。
* Recursively navigate to return a BeanWrapper for the nested property path.
* @param propertyPath property property path, which may be nested
* @return a BeanWrapper for the target bean
*/
protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
// 获取属性解析的位置,例如属性路径为“beanA.beanB”,此时获取的pos=5
// 如果参数中不包含“.”, pos=-1,这里取得的是第一个“.”的位置
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
// Handle nested properties recursively.
// 如果存在嵌套的情况,就需要递归查询,直到找到对应的 BeanWrapper 实例为止。
if (pos > -1) {
// 得到的值为:beanA
String nestedProperty = propertyPath.substring(0, pos);
// 得到的值为:beanB
String nestedPath = propertyPath.substring(pos + 1);
// 通过 beanA 得到嵌套的 BeanWrapper 实例
BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty);
// 递归查询通过 beanA 得到嵌套的 BeanWrapper 实例的属性值 beanB
return nestedBw.getBeanWrapperForPropertyPath(nestedPath);
}
// 如果不存在嵌套的情况,返回自己本身的引用
else {
return this;
}
}
/**
* 为指定的嵌套属性恢复一个 BeanWrapper 实例,如果没有缓存中找到,重新创建一个。
* Retrieve a BeanWrapper for the given nested property.
* Create a new one if not found in the cache.
* <p>Note: Caching nested BeanWrappers is necessary now,
* to keep registered custom editors for nested properties.
* @param nestedProperty property to create the BeanWrapper for
* @return the BeanWrapper instance, either cached or newly created
*/
private BeanWrapperImpl getNestedBeanWrapper(String nestedProperty) {
// 如嵌套的 BeanWrapper 缓存为空,重建一个
if (this.nestedBeanWrappers == null) {
this.nestedBeanWrappers = new HashMap<String, BeanWrapperImpl>();
}
// Get value of bean property.
PropertyTokenHolder tokens = getPropertyNameTokens(nestedProperty);
String canonicalName = tokens.canonicalName;
// 获取对应的属性值(留在后面讲解)
Object propertyValue = getPropertyValue(tokens);
if (propertyValue == null) {
if (this.autoGrowNestedPaths) {
propertyValue = setDefaultValue(tokens);
}
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + canonicalName);
}
}
// Lookup cached sub-BeanWrapper, create new one if not found.
BeanWrapperImpl nestedBw = this.nestedBeanWrappers.get(canonicalName);
if (nestedBw == null || nestedBw.getWrappedInstance() != propertyValue) {
if (logger.isTraceEnabled()) {
logger.trace("Creating new nested BeanWrapper for property '" + canonicalName + "'");
}
// 构建一个新的 BeanWrapper 实例,把自己作为嵌套父类,嵌套路径=当前路径+嵌套Bean标识+“.”
nestedBw = newNestedBeanWrapper(propertyValue, this.nestedPath + canonicalName + NESTED_PROPERTY_SEPARATOR);
// Inherit all type-specific PropertyEditors.
// 复制属性注册器到嵌套的 BeanWrapper 中
copyDefaultEditorsTo(nestedBw);
copyCustomEditorsTo(nestedBw, canonicalName);
// 嵌套 BeanWrapper 缓存添加新建的 BeanWrapper 实例
this.nestedBeanWrappers.put(canonicalName, nestedBw);
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Using cached nested BeanWrapper for property '" + canonicalName + "'");
}
}
return nestedBw;
}
/**
* 解析指定的属性名称,并把它赋值到对应的属性标识中(即保存在 PropertyTokenHolder 中)
* Parse the given property name into the corresponding property name tokens.
* @param propertyName the property name to parse
* @return representation of the parsed property tokens
*/
private PropertyTokenHolder getPropertyNameTokens(String propertyName) {
// 例如输入“xxxSet[1]”
PropertyTokenHolder tokens = new PropertyTokenHolder();
String actualName = null;
List<String> keys = new ArrayList<String>(2);
int searchIndex = 0;
while (searchIndex != -1) {
// 从指定的索引位置查询“[”的位置
int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex);
searchIndex = -1;
// 如果能找到,找对应的“]”的位置
if (keyStart != -1) {
int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length());
if (keyEnd != -1) {
if (actualName == null) {
// actualName = xxxSet
actualName = propertyName.substring(0, keyStart);
}
// key = 1
String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) {
key = key.substring(1, key.length() - 1);
}
keys.add(key);
// 重置查询索取到“]”符号后面
searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length();
}
}
}
// tokens.actualName = xxxSet
tokens.actualName = (actualName != null ? actualName : propertyName);
// tokens.canonicalName = xxxSet
tokens.canonicalName = tokens.actualName;
if (!keys.isEmpty()) {
// tokens.canonicalName = xxxSet[1]
tokens.canonicalName +=
PROPERTY_KEY_PREFIX +
StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
PROPERTY_KEY_SUFFIX;
// tokens.keys = [1]
tokens.keys = StringUtils.toStringArray(keys);
}
// 输入"xxxSet[1]",得到:
// tokens.actualName="xxxSet",tokens.canonicalName="xxxSet[1]",tokens.keys=["1"]
// 输入"xxxSet",得到:
// tokens.actualName="xxxSet",tokens.canonicalName="xxxSet",tokens.keys=null
return tokens;
}
- 获取属性值
再来说说获取属性值,BeanWrapperImpl 提供了 getPropertyValue(String propertyName) 来处理。下面看看源码,了解实现方式:
@Override
public Object getPropertyValue(String propertyName) throws BeansException {
// 获取 propertyName 对应的 BeanWrapper 实例。如果包含嵌套,获取最后一层嵌套的 BeanWrapper 实例
BeanWrapperImpl nestedBw = getBeanWrapperForPropertyPath(propertyName);
// 构建访问属性的 property 属性名称的标识
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
// 执行获取属性值
return nestedBw.getPropertyValue(tokens);
}
private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
// 获取对应的属性描述定义
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);
// 如果无法获取getter方法,直接异常
if (pd == null || pd.getReadMethod() == null) {
throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
}
final Method readMethod = pd.getReadMethod();
try {
// 如果 getter 访问不是 pulbic 类型,并且不是可以获取的,设置成可以访问
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
}
else {
readMethod.setAccessible(true);
}
}
// 通过 getter 方法获取对应的属性值
Object value;
if (System.getSecurityManager() != null) {
try {
value = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return readMethod.invoke(object, (Object[]) null);
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
value = readMethod.invoke(object, (Object[]) null);
}
// 如果需要获取具体集合中某项值,指定了keys
if (tokens.keys != null) {
if (value == null) {
// 如果设置了自动生成嵌套的值属性,设置默认值
if (this.autoGrowNestedPaths) {
value = setDefaultValue(tokens.actualName);
}
else {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value of property referenced in indexed " +
"property path '" + propertyName + "': returned null");
}
}
String indexedPropertyName = tokens.actualName;
// apply indexes and map keys
for (int i = 0; i < tokens.keys.length; i++) {
String key = tokens.keys[i];
// 如果属性值为 null,抛出异常
if (value == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
"Cannot access indexed value of property referenced in indexed " +
"property path '" + propertyName + "': returned null");
}
// 如果对应的属性是数组类型
else if (value.getClass().isArray()) {
int index = Integer.parseInt(key);
value = growArrayIfNecessary(value, index, indexedPropertyName);
value = Array.get(value, index);
}
// 如果对应的属性是List类型
else if (value instanceof List) {
int index = Integer.parseInt(key);
List list = (List) value;
growCollectionIfNecessary(list, index, indexedPropertyName, pd, i + 1);
value = list.get(index);
}
// 如果对应的属性是Set类型
else if (value instanceof Set) {
// Apply index to Iterator in case of a Set.
Set set = (Set) value;
int index = Integer.parseInt(key);
if (index < 0 || index >= set.size()) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Cannot get element with index " + index + " from Set of size " +
set.size() + ", accessed using property path '" + propertyName + "'");
}
Iterator it = set.iterator();
for (int j = 0; it.hasNext(); j++) {
Object elem = it.next();
if (j == index) {
value = elem;
break;
}
}
}
// 如果对应的属性是Map类型
else if (value instanceof Map) {
Map map = (Map) value;
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
// 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 = mapKeyType != null ? TypeDescriptor.valueOf(mapKeyType) : TypeDescriptor.valueOf(Object.class);
Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType, typeDescriptor);
value = map.get(convertedMapKey);
}
// 其他情况,不是集合类型,不支持,抛出异常
else {
throw new InvalidPropertyException(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 + "]");
}
indexedPropertyName += PROPERTY_KEY_PREFIX + key + PROPERTY_KEY_SUFFIX;
}
}
return value;
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Index of out of bounds in property path '" + propertyName + "'", ex);
}
catch (NumberFormatException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
catch (TypeMismatchException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Invalid index in property path '" + propertyName + "'", ex);
}
catch (InvocationTargetException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Getter for property '" + actualName + "' threw exception", ex);
}
catch (Exception ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
}
}
通过上面的代码分析,我们了解了 BeanWrapper 是如何获取属性值以及设置属性值的。同时 BeanWrapperImpl 通过定义嵌套路径来解析我们真正的需要的属性,并且智能的来判断我们意图。值得一提的是,对比设置方法和获取方法,我们会发现在设置方法中其并没有对 Set 进行处理,但是我可以通过 Set[index] 来获取对应的值。这是因为 Set 是要去重的,在设置的时候无法判断他的索引位置,但是在获取的时候可以通过遍历来获取对应 index 的值。
2.5 BeanWrapper 中类型转换
上面在分析设置 Bean 属性值时,使用了 convertIfNecessary 方法,这个方法中会判断是否需要类型转换。下面我们来分析这个类型转换。
- 类型转换代理实例构建
BeanWrapperImpl 中的类型转换是通过 TypeConverterDelegate 来实现的。构建这个实例发生在我们构建 BeanWrapper 实例的时候。
public BeanWrapperImpl(boolean registerDefaultEditors) {
if (registerDefaultEditors) {
registerDefaultEditors();
}
this.typeConverterDelegate = new TypeConverterDelegate(this);
}
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Bean object must not be null");
this.object = object;
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object);
this.nestedBeanWrappers = null;
this.typeConverterDelegate = new TypeConverterDelegate(this, object);
setIntrospectionClass(object.getClass());
}
- 类型转换
TypeConverterDelegate 重要提供的服务是 convertIfNecessary 。这个方法提供了几个重载方法,如下:
/**
* Convert the value to the specified required type.
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @param methodParam the method parameter that is the target of the conversion
* (may be <code>null</code>)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public <T> T convertIfNecessary(Object newValue, Class<T> requiredType, MethodParameter methodParam)
throws IllegalArgumentException {
return convertIfNecessary(null, null, newValue, requiredType,
(methodParam != null ? new TypeDescriptor(methodParam) : TypeDescriptor.valueOf(requiredType)));
}
/**
* Convert the value to the required type for the specified property.
* @param propertyName name of the property
* @param oldValue the previous value, if available (may be <code>null</code>)
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
public <T> T convertIfNecessary(
String propertyName, Object oldValue, Object newValue, Class<T> requiredType)
throws IllegalArgumentException {
return convertIfNecessary(propertyName, oldValue, newValue, requiredType, TypeDescriptor.valueOf(requiredType));
}
/**
* Convert the value to the required type (if necessary from a String),
* for the specified property.
* @param propertyName name of the property
* @param oldValue the previous value, if available (may be <code>null</code>)
* @param newValue the proposed new value
* @param requiredType the type we must convert to
* (or <code>null</code> if not known, for example in case of a collection element)
* @param typeDescriptor the descriptor for the target property or field
* @return the new value, possibly the result of type conversion
* @throws IllegalArgumentException if type conversion failed
*/
@SuppressWarnings("unchecked")
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
Object convertedValue = newValue;
// Custom editor for this type?
// 查找匹配的 PropertyEditor
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
ConversionFailedException firstAttemptEx = null;
// No custom editor but custom ConversionService specified?
// 如果没有自定义的 PropertyEditor,但是定义了转换服务(conversionService)
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
if (editor == null && conversionService != null && convertedValue != null && typeDescriptor != null) {
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
TypeDescriptor targetTypeDesc = typeDescriptor;
if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {
try {
return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);
}
// 如果无法转换成功,走下面的默认处理逻辑
catch (ConversionFailedException ex) {
// fallback to default conversion logic below
firstAttemptEx = ex;
}
}
}
// Value not of required type?
// 如果找到了 PropertyEditor,或者提供转换的新值不是指定的转换类型
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
// 如果目标类型是集合类型,并且对应的值是 string 类型
if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
// 处理枚举类型集合
if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
}
}
// 如果对应自定义的 PropertyEditer,使用默认的 PropertyEditor
if (editor == null) {
editor = findDefaultEditor(requiredType, typeDescriptor);
}
// 执行类型转换,获取转换后的值
convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
}
// 如果定义了需要转换的类型
if (requiredType != null) {
// Try to apply some standard type conversion rules if appropriate.
// 如果标准的的转换规则存在,尝试去适配标准的转换器
// 如果通过上面的转换(有自定义的转换或者需要转换的的值不是目标类型)能够得到转换后的值
if (convertedValue != null) {
// 如果是数组,通过数组转换返回
// 如果对应的值是 spring,指定的转换数组的内部类型是枚举,用逗号分隔值
if (requiredType.isArray()) {
// Array required -> apply appropriate conversion of elements.
if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
}
return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
}
// 如果对应的转换值是集合类型,通过集合转换
else if (convertedValue instanceof Collection) {
// Convert elements to target type, if determined.
convertedValue = convertToTypedCollection(
(Collection) convertedValue, propertyName, requiredType, typeDescriptor);
}
// 如果对应的转换值是Map类型,通过Map转换器转换
else if (convertedValue instanceof Map) {
// Convert keys and values to respective target type, if determined.
convertedValue = convertToTypedMap(
(Map) convertedValue, propertyName, requiredType, typeDescriptor);
}
// 如果对应的转换类型不是数组类型,对应的值是数组类型,取第一个值作为转换值
if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
convertedValue = Array.get(convertedValue, 0);
}
// 如果对应转换类型是String类型,转化值是标准内部类型,直接转换为string返回
if (String.class.equals(requiredType) && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
// We can stringify any primitive value...
return (T) convertedValue.toString();
}
// 处理枚举类型,值是枚举对应的名称
else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
if (!requiredType.isInterface() && !requiredType.isEnum()) {
try {
Constructor strCtor = requiredType.getConstructor(String.class);
return (T) BeanUtils.instantiateClass(strCtor, convertedValue);
}
catch (NoSuchMethodException ex) {
// proceed with field lookup
if (logger.isTraceEnabled()) {
logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
}
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
}
}
}
String trimmedValue = ((String) convertedValue).trim();
if (requiredType.isEnum() && "".equals(trimmedValue)) {
// It's an empty enum identifier: reset the enum value to null.
return null;
}
convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
}
}
// 如果转换后的值不是指定的转换类型,异常
if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
if (firstAttemptEx != null) {
throw firstAttemptEx;
}
// Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
StringBuilder msg = new StringBuilder();
msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
if (propertyName != null) {
msg.append(" for property '").append(propertyName).append("'");
}
if (editor != null) {
msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
"] returned inappropriate value of type [").append(
ClassUtils.getDescriptiveType(convertedValue)).append("]");
throw new IllegalArgumentException(msg.toString());
}
else {
msg.append(": no matching editors or conversion strategy found");
throw new IllegalStateException(msg.toString());
}
}
}
if (firstAttemptEx != null) {
if (editor == null && convertedValue == newValue) {
throw firstAttemptEx;
}
logger.debug("Original ConversionService attempt failed - ignored since " +
"PropertyEditor based conversion eventually succeeded", firstAttemptEx);
}
return (T) convertedValue;
}
3. 实例化的各个流程
再次回顾一下上次分享中的 Bean 依赖注入的大概过程:
BeanFactory.getBean → AbstarctBeanFactory.doGetBean → AbstractAutowireCapableBeanFactory.createBean
中间会递归查询依赖,从而完成 Bean 的依赖注入过程。这个过程也是 Bean 实例化过程。
3.1 创建Bean实例
创建 Bean 实例当调用到 AbstractAutowireCapableBeanFactory.createBean 方法后,会转发到 AbstractAutowireCapableBeanFactory.doCreateBean 方法。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
// 初始化 Bean 实例,创建 Bean 实例的 BeanWrapper。
// 如果是单例,需要从容器实例缓存中获取,并删除缓存
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
// 给你一次修改 bean 定义的机会,同时你可以来检查bean定义的相关属性
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 可以做代理,改变Bean的引用的地方(SmartInstantiationAwareBeanPostProcessor)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 组装 Bean,后面会讲到
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 二次验证提前暴露引用(SmartInstantiationAwareBeanPostProcessor)的处理是否正确
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
/**
* 通过指定的实例化策略初始化一个新的的 Bean 实例。初始化策略:工厂方法、自动装载构造方法、默认简单构造方法
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @return BeanWrapper for the new instance
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
Class beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 如果配置了通过工厂方法构造,查找对应的工厂方法来初始化 Bean 实例
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean…
// 如果是重新创建同一个 bean,可以根据 BeanDefinition 中的标识来判断
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已经通过构造方法或者的构造工厂处理过 bean 定义
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// 剩下的就是需要去查询使用那个构造方法,如果能找到对应的构造方法,使用构造方法来创建实例,
// 否则就是使用默认构造方法。例如经常使用的默认无参数构造方法
// Need to determine the constructor…
// 如果定义了对应的 BeanPostProcessor,定义使用某个构造方法,使用之
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 默认使用无参数构造方法
return instantiateBean(beanName, mbd);
}
4. 自动注入实现方式
4.1 组装 Bean
你已经厌倦了上面上面长篇的累述,你还没有了解到 BeanWrapper 和组装 Bean 的用途,那么我可以高兴的告诉你,下面我就分析 Bean 的组装,了解 BeanWrapper 的用途。当了解完这个下面这个方法后,我们这次的分享就基本上结束了。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean:
/**
* 根据 BeanWrapper,来组装 Bean 实例
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
// 从 BeanDefinition 中获取所有的的 Bean 属性
PropertyValues pvs = mbd.getPropertyValues();
// 如果没有指定 BeanWrapper,但是有 Bean 属性,异常返回,否则跳过处理
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;
// 给你一次扩展的 BeanPostProcessor 的机会,来在 Bean 实例化后做点儿自己想干的事情
// 回想一下对应的 InstantiationAwareBeanPostProcessor 什么时间会在初始化前调用?
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);
// 在 Bean 发布可以使用前,检查依赖是否完整等
// 如果定义了InstantiationAwareBeanPostProcessor,你可以自定义自己的检查逻辑
// 也可以强制加载自己的依赖,例如注解 Resource 的实现等。
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
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);
}
}
// 对Bean相关的属性开始发布赋值,可能递归 getBean。
applyPropertyValues(beanName, mbd, bw, pvs);
}
/**
* 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;
}
// 构建对应的属性值处理器
// 属性值处理器,主要完成对应对依赖的属性的构建
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
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 {
// 通过 BeanWrapper 来把所有的属性值赋值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
4.2 详解各个自动注入代码
属性名称自动装载
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
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");
}
}
}
}
属性类型自动装载
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);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
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());
DependencyDescriptor 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);
}
}
}
5. 小结
通过上面的分享,我们了解了 Bean 创建过程。一般情况下,我们会使用构造函数或者setter方法来进行依赖。BeanWrapper能很好的处理getter和setter方式;构造方法、工厂方法的形式构建 bean, Spring也做了很好的处理。但是我们常用“Resouce”方式,即没有构造方法、也没有setter方法,又该如何处理呢?这个留在下一次分享,关于 BeanPostProcessor。