spring源码解析 -- 注入属性

314 阅读5分钟

Spring源码解析 -- 读取bean元数据
spring源码解析 -- 构造bean
spring源码解析 -- 注入属性
spring源码解析 -- Spring Context
Spring源码解析 -- AOP原理(1)
Spring源码解析 -- AOP原理(2)
Spring源码解析 -- SpringMvc原理

源码分析基于spring 4.3.x 前面的文件已经解析了Spring构造bean(未注入属性)的过程,现在继续解析spring注入属性的过程。

在解析spring读取xml配置的文章说过,spring会将xml属性配置信息转化为spring内部的表示类,并结合属性name,type等元数据构造PropertyValue,存放在BeanDefinition#propertyValues。
而在解析spring构造bean的文章中说过,spring注入属性的方法在 AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
	protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
		PropertyValues pvs = mbd.getPropertyValues();

		...
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {	// #1
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {	// #2
						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) {	// #3
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {	// #4
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {	// #5
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			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);
			}
		}

		applyPropertyValues(beanName, mbd, bw, pvs);	// #6
	}

}

#1 查找spring上下文是否存在InstantiationAwareBeanPostProcessor。
InstantiationAwareBeanPostProcessor也是spring提供的扩展接口,它继承自BeanPostProcessor,并添加了postProcessBeforeInstantiation,postProcessAfterInstantiation,postProcessPropertyValues这三个方法。
#2 存在InstantiationAwareBeanPostProcessor,调用postProcessAfterInstantiation方法
#3 处理通过name自动装配
#4 处理通过type自动装配
#5 调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues扩展方法,很重要,这里完成@Value,@Autowired注解的解析,后面有对应文章解析
#6 解析BeanDefinition#propertyValues中的属性

AbstractAutowireCapableBeanFactory#autowireByName

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);	// #1
			pvs.add(propertyName, bean);	// #2
			registerDependentBean(propertyName, beanName);	// #3
			if (logger.isDebugEnabled()) {
				logger.debug("Added autowiring by name from bean name '" + beanName +
						"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
			}
		}
		else {
			...
		}
	}
}

#1 通过name获取bean
#2 添加到BeanDefinition#propertyValues,交给下面流程处理
#3 声明bean之间的依赖,bean销毁时要判断bean的依赖
autowireByType这里就不复述了。

AbstractAutowireCapableBeanFactory#applyPropertyValues

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	...

	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);	// #1
		}
		else {
			String propertyName = pv.getName();
			Object originalValue = pv.getValue();
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);	// #2
			Object convertedValue = resolvedValue;
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);	// #3
			}
			// 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);	// #4
				}
				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;	// #5
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
	if (mpvs != null && !resolveNecessary) {
		mpvs.setConverted();
	}

	// Set our (possibly massaged) deep copy.
	try {
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));	// #6
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}

#1 属性已处理,直接复用
#2 解析bean引用(如RuntimeBeanReference,RuntimeBeanNameReference),获取引用的bean,对于集合属性,如ManagedArray,ManagedList,如果集合中的元素是bean引用,也会被解析。
TypedStringValue则会提取value的值。
#3 根据目标属性进行转换
xml配置都是string,如果属性的类型是long,date,这里进行转换
#4 缓存结果,避免每次构建bean时都重复操作
#5 无法缓存,只能复制结果用于后面流程
#6 赋值给bean

转化

下面看看转化过程 AbstractAutowireCapableBeanFactory#convertForProperty

private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
	if (converter instanceof BeanWrapperImpl) {			
		return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);	// #1
	}
	else {
		PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
		MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
		return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);	// #2
	}
}

#1 默认的转化方式 #2 使用自定义转化方式

看看默认的转化方式,BeanWrapperImpl#convertForProperty -> TypeConverterDelegate#convertIfNecessary

public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
		Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {

	PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

	ConversionFailedException conversionAttemptEx = null;

	ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
	if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {	// #1
		TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
		if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
			try {
				return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
			}
			catch (ConversionFailedException ex) {
				// fallback to default conversion logic below
				conversionAttemptEx = ex;
			}
		}
	}

	Object convertedValue = newValue;

	if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {	// #2
		if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
				convertedValue instanceof String) {
			TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
			if (elementTypeDesc != null) {
				Class<?> elementType = elementTypeDesc.getType();
				if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
					convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
				}
			}
		}
		if (editor == null) {
			editor = findDefaultEditor(requiredType);
		}
		convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
	}

	boolean standardConversion = false;

	if (requiredType != null) {
		// Try to apply some standard type conversion rules if appropriate.

		if (convertedValue != null) {
			if (Object.class == requiredType) {
				return (T) convertedValue;
			}
			else if (requiredType.isArray()) {	// #3
				if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
					convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
				}
				return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
			}
			...
		}
		else {
			// convertedValue == null
			if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
				convertedValue = javaUtilOptionalEmpty;	// #4
			}
		}

		if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
			... // #5
		}
	}

	

	return (T) convertedValue;
}

#1 PropertyEditor为空,使用ConversionService
#2 PropertyEditor不为空,使用PropertyEditor
#3 处理数组,集合等类型的属性,这里会遍历集合元素,递归调用convertIfNecessary转化,再收集处理结果。
#4 对转化结果是空值的情况进行处理
#5 异常情况,会重复调用一遍conversionService
PropertyEditor,ConversionService都可以自定义属性的转化操作。

赋值

AbstractAutowireCapableBeanFactory#applyPropertyValues方法#6步骤负责赋值给bean的属性。
这里调用AbstractNestablePropertyAccessor#setPropertyValues -> AbstractNestablePropertyAccessor#setPropertyValue

public void setPropertyValue(PropertyValue pv) throws BeansException {
	PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
	if (tokens == null) {
		String propertyName = pv.getName();
		AbstractNestablePropertyAccessor nestedPa;
		try {
			nestedPa = getPropertyAccessorForPropertyPath(propertyName);	// #1
		}
		catch (NotReadablePropertyException ex) {
			throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
					"Nested property in path '" + propertyName + "' does not exist", ex);
		}
		tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
		if (nestedPa == this) {
			pv.getOriginalPropertyValue().resolvedTokens = tokens;
		}
		nestedPa.setPropertyValue(tokens, pv);	// #2
	}
	else {
		setPropertyValue(tokens, pv);
	}
}

#1 根据propertyName获取不同的属性访问器(set方法引用)
getPropertyAccessorForPropertyPath返回的是BeanWrapperImpl,他继承了AbstractNestablePropertyAccessor。
这里支持嵌套属性,如Blog中存在author属性,而Author存在name属性,对Blog的bean可配置author.name,这里返回的是blog的author属性对应的BeanWrapperImpl。

#2 AbstractNestablePropertyAccessor#setPropertyValue -> AbstractNestablePropertyAccessor#processLocalProperty -> PropertyHandler#setValue -> BeanWrapperImpl#setValue 可以看到直接调用set方法了。

如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!