spring源碼解析 -- 注入屬性

Spring源碼解析 -- 讀取bean元數據
spring源碼解析 -- 構造bean
spring源碼解析 -- 注入屬性
spring源碼解析 -- Spring Context
Spring源碼解析 -- AOP原理(1)
Spring源碼解析 -- AOP原理(2)
Spring源碼解析 -- SpringMvc原理java

源碼分析基於spring 4.3.x 前面的文件已經解析了Spring構造bean(未注入屬性)的過程,如今繼續解析spring注入屬性的過程。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#autowireByNamebash

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#applyPropertyValuesapp

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#convertForPropertypost

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 使用自定義轉化方式ui

看看默認的轉化方式,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方法了。

若是您以爲本文不錯,歡迎關注個人微信公衆號,您的關注是我堅持的動力!

相關文章
相關標籤/搜索