Spring源碼解析 -- 讀取bean元數據
spring源碼解析 -- 構造bean
spring源碼解析 -- 注入屬性
spring源碼解析 -- Spring Context
Spring源碼解析 -- AOP原理(1)
Spring源碼解析 -- AOP原理(2)
Spring源碼解析 -- SpringMvc原理 java
前面的文件已經解析了Spring構造bean(未注入屬性)的過程,如今繼續解析spring注入屬性的過程。spring
在解析spring讀取xml配置的文章說過,spring會將xml屬性配置信息轉化爲spring內部的表示類,並結合屬性name,type等元數據構造PropertyValue,存放在BeanDefinition#propertyValues。
而在解析spring構造bean的文章中說過,spring注入屬性的方法在
AbstractAutowireCapableBeanFactory#populateBeansegmentfault
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#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
賦值給beanpost
下面看看轉化過程
AbstractAutowireCapableBeanFactory#convertForPropertyui
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
使用自定義轉化方式this
看看默認的轉化方式,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方法了。
若是您以爲本文不錯,歡迎關注個人微信公衆號,您的關注是我堅持的動力!