`
游伯度
  • 浏览: 22755 次
  • 性别: 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 Ioc 注解 依赖注入

    ### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...

    Spring-ioc-jar

    4. **依赖注入**: 在实例化Bean的同时,Spring会根据Bean定义中的依赖关系,自动将所需的其他Bean注入到当前Bean中。依赖注入可以通过属性注入(setter方法)、构造器注入或者方法注入实现。 5. **生命周期管理**: ...

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

    Bean 的生命周期流程包括实例化、依赖注入、初始化、使用、销毁等阶段。在 Bean 的生命周期中,我们需要了解 Bean 的生命周期案例,以便更好地理解 Bean 的生命周期。 本文主要研究了 Spring 框架中 Bean 的实例化...

    Spring_IOC-v(上)笔记

    Spring_IOC-v(上)笔记是关于 Spring 框架中的 IoC(控制反转)技术的笔记,主要介绍了 IoC 的概念、依赖注入、Bean 的设置、Spring 组件的管理等知识点。 IoC 技术是 Spring 框架的核心概念之一,它的主要思想...

    撸一撸Spring Framework-IoC-BeanDefinition(csdn)————程序.pdf

    总结来说,BeanDefinition是Spring IoC容器的核心组成部分,它封装了bean的所有配置信息,使容器能够根据这些信息实例化、配置、管理bean,从而实现了控制反转。通过XML配置文件,我们可以轻松地定义bean及其属性,...

    Spring实例化Bean顺序

    4. **启动后处理器(BeanPostProcessor)**:这些是特殊类型的Bean,它们在所有常规Bean实例化之后,但初始化之前进行处理。它们的实例化顺序由`@Order`注解决定,或者通过实现`Ordered`接口来控制。 5. **...

    spring学习----工厂Bean

    工厂Bean允许开发者在对象实例化时进行更复杂的控制,比如引入特定的初始化过程、依赖注入或者资源管理。这篇博文将深入探讨工厂Bean的工作原理和使用场景。 首先,让我们理解什么是Bean。在Spring中,Bean是IoC...

    浅谈Spring IoC容器的依赖注入原理

    浅谈Spring IoC容器的依赖注入...Spring IoC容器的依赖注入原理是通过IoC容器初始化和Bean实例化两个阶段来实现的。在这个过程中,IoC容器会根据Bean的依赖关系来实例化和提供Bean对象,从而实现了自动依赖注入机制。

    springIoc实现原理

    2. **Bean实例化**:根据BeanDefinition,Spring容器创建Bean实例,可以是单例或多例。 3. **依赖注入**:Spring容器根据BeanDefinition中的依赖关系,为Bean注入依赖对象。 4. **初始化**:Spring容器调用Bean的...

    spring IOC反射装载bean

    这里,`init-method`指定的`initMethod`方法会在Bean实例化后被调用。 除了XML配置,Spring还支持基于注解的配置,如`@Component`、`@Service`、`@Repository`和`@Controller`,以及`@Autowired`用于自动装配依赖。...

    Spring Ioc源码分析系列--自动注入循环依赖的处理.doc

    Spring Ioc 源码分析系列--自动注入循环依赖的处理 本篇文章主要讲解了 Spring Ioc 源码分析系列中自动注入循环依赖的处理机制。循环依赖是 Spring 框架中一个经典的问题,也是面试中常被问到的问题。本篇文章将...

    Java-Spring-SpringIoC容器-SpringIoC的学习

    Spring IoC容器通过XML配置或注解实现了对象的创建、管理和依赖注入,极大地简化了Java应用的复杂性。理解并熟练运用Spring IoC,能够帮助开发者构建更灵活、易于测试和维护的系统。在实际开发中,还可以结合@...

    Spring IOC Annotation 注入 学习实例

    学习Spring IOC Annotation注入,首先需要理解Bean的生命周期,包括初始化、使用和销毁的过程。然后,通过编写带有注解的类,创建Bean定义,并让Spring容器管理这些Bean。容器会在适当的时间调用`@PostConstruct`...

    SpingIOC注入实例化bean

    在传统的编程模式中,开发者需要手动创建和管理对象,而在Spring IOC中,这个过程被反转,由Spring容器负责对象的创建、初始化、装配以及管理,开发者只需声明对象间的依赖,无需关心具体的实例化过程。 1. **Bean...

    spring-demo02-IOC-DI案例.zip

    Spring 框架是 Java 开发中不可或缺的一部分,它以其强大的依赖注入(Dependency Injection, DI)和控制反转(Inversion of Control, IOC)特性而闻名。在这个名为“spring-demo02-IOC-DI案例”的压缩包中,我们将...

    maven-spring-ioc

    Spring IoC通过XML配置文件实现了对象的实例化和依赖注入,有效地降低了对象间的耦合,提高了代码的可读性和可维护性。理解并熟练运用Spring的IoC机制是成为一名优秀的Java开发者的关键步骤之一。在实际项目中,结合...

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

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

    Spring Bean创建初始化流程.docx

    进入`doGetBean()`方法,这是Bean实例化的关键步骤。`doGetBean()`会处理Bean的依赖注入、类型检查等操作。 7. **创建Bean**: `createBean(beanName, mbd, args)`在`AbstractAutowireCapableBeanFactory`中实现...

Global site tag (gtag.js) - Google Analytics