`
游伯度
  • 浏览: 22016 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring IOC - 依赖注入(Bean实例化过程)

阅读更多

双十一过去了,终于可以把这篇博客补上了。

本文将分析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,那么访问BeanABeanB属性的路径是“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 设置和获取获取属性值前,我们先了解一下 PropertyTokenHolderPropertyTokenHolder 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能很好的处理gettersetter方式;构造方法、工厂方法的形式构建 bean Spring也做了很好的处理。但是我们常用“Resouce”方式,即没有构造方法、也没有setter方法,又该如何处理呢?这个留在下一次分享,关于 BeanPostProcessor

 

  • 大小: 38.2 KB
分享到:
评论

相关推荐

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    08-IoC配置-bean的生命周期控制

    通过构造器或工厂方法创建Bean实例 为Bean的属性设置值和对其它Bean的引用 调用Bean的初始化方法 Bean可以使用了 当容器关闭时,调用Bean的销毁方法 在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 ...

    maven-spring-ioc

    spring IoC, 使用配置文件方式配置Bean的实例化和依赖注入

    详解Spring框架---IOC装配Bean

    本篇文章主要介绍了详解Spring框架---IOC装配Bean,提供了三种方式实例化Bean,具有一定的参考价值,有兴趣的可以了解一下。

    Spring bean的实例化和IOC依赖注入详解

    主要介绍了Spring bean的实例化和IOC依赖注入详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    spring_Ioc

    spring ioc 采用注解方式实现Bean实例化和依赖注入

    SpringIoC容器和Bean管理学习记录-SSM框架的学习与应用

    1.spring中bean实例化的俩种方式 2.spring中bean的各种元素如何使用 3.spring中的bean管理 4.spring中不同类型bean的作用域 5.spring中bean的生命周期 通过我的项目,可以跟着学习SPringIoC容器和Bean管理,帮助你...

    浅谈springioc实例化bean的三个方法

    下面小编就为大家带来一篇浅谈springioc实例化bean的三个方法。小编觉得挺不错的,现在就想给大家,也给大家做个参考。一起跟随小编过来看看吧

    模拟实现Spring的IOC

    1、Spring主要两个作用:实例化Bean,动态装配Bean。并将所有的bean放到spring容器中,调用时从容器中取。Spring容器就是一个bean的Map:private Map, Object&gt; beans = new HashMap, Object&gt;(); 2、本工程,模拟...

    深入解析Spring IoC源码:核心机制与实践应用

    本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...

    深入解析Spring IoC:源码与实践指南

    Spring框架的核心在于其强大的IoC(控制反转)机制,该机制为Java应用提供了一种优雅的依赖注入方式。本文深入探讨了Spring IoC容器的加载过程及其源码实现,揭示了Spring中最为根本的概念之一。这包括从...

    spring(一)–概念和历史/hellospring/IOC创建对象的方式/Spring配置/set注入/c命名和p命名空间注入/bean的作用域

    文章目录一、概念和历史二、hellospring三、IOC创建对象的方式四、Spring配置五、set注入–属性注入六、c命名和p命名空间注入七 、bean的作用域 一、概念和历史 Spring的形成,最初来自Rod Jahnson所著的一本很有...

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例 spring jar 包详解spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下...

    Spring-IOC手动模拟实现-利用dom4解析xml文件

    通过反射实例化得到对应的实例化对象,放置在map中(map是键值对,可根据id获取值)(遍历list获取对应的class属性,利用class。formName(class).newIntance()) * 4.通过id获取指定的实例化对象 * */ 底层工厂...

    JAVA spring 系列案例50个和学习资料

    Spring系列第2篇:控制反转(IoC)与依赖注入(DI)。Spring系列第3篇:Spring容器基本使用及原理。Spring系列第4篇:xml中bean定义详解(-)Spring系列第5篇:创建bean实例这些方式你们都知道?Spring系列第6篇:玩转...

    spring-framework-3.1.0.RELEASE.zip

    容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个...

    springIOC案例

    包含spring的和Junit的jar包,采用Junit测试,一共四个案例,主要讲述:1.怎么利用IOC容器获得实例化对象;...3.静态工厂方式实例化Bean;4.依赖和依赖注入的几种方式。以及一张&lt;&lt;IOC应用&gt;&gt;的ppt。

    Spring攻略PDF版

     3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案   3.2.3 实现方法   3.3 解决构造器歧义   3.3.1 问题描述   3.3.2 解决方案   3.3.3 实现方法   第4章 高级...

    Spring攻略英文版(附带源码)

     3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案   3.2.3 实现方法   3.3 解决构造器歧义   3.3.1 问题描述   3.3.2 解决方案   3.3.3 实现方法   第4章 高级Spring IoC...

    Spring攻略中文版PDF

     3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案   3.2.3 实现方法   3.3 解决构造器歧义   3.3.1 问题描述   3.3.2 解决方案   3.3.3 实现方法   第4章 高级...

Global site tag (gtag.js) - Google Analytics