美文网首页
spring源码深度解析—IOC 之属性填充

spring源码深度解析—IOC 之属性填充

作者: Java架构小喳喳 | 来源:发表于2019-07-09 17:18 被阅读0次

正文

doCreateBean() 主要用于完成 bean 的创建和初始化工作,我们可以将其分为四个过程:

1、createBeanInstance() 实例化 bean/

2、populateBean() 属性填充

3、循环依赖的处理/

4、initializeBean() 初始化 bean

protectedvoidpopulateBean(String beanName, RootBeanDefinition mbd,BeanWrapper bw) {

PropertyValues pvs = mbd.getPropertyValues();

if(bw == null) {

if(!pvs.isEmpty()) { 

 throw newBeanCreationException(

mbd.getResourceDescription(),beanName, "Cannot apply property values to null instance"); 

}

else{

 // Skip propertypopulation phase for null instance.

return; 

}

 }

// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the

// state of thebean before properties are set. This canbe used, for example,

// to support styles offieldinjection.

boolean continueWithPropertyPopulation = true;

if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

for (BeanPostProcessor bp : getBeanPostProcessors()) {

if(bp instanceof InstantiationAwareBeanPostProcessor) {

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;

//返回值为是否继续填充bean

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 valuesbased on autowireby nameifapplicable. 

 //根据名称自动注入

if(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 

 autowireByName(beanName, mbd,bw, newPvs);

 }

//Add property valuesbased on autowireby typeifapplicable. 

 //根据类型自动注入

if(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 

 autowireByType(beanName, mbd,bw, newPvs);

 }

pvs = newPvs; 

}

 //后处理器已经初始化

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 

//需要依赖检查

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 

//需要依赖检查

boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if(hasInstAwareBpps||needsDepCheck) {

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) { 

 //依赖检查,对应depends-on属性,3.0已经弃用此属性 

 checkDependencies(beanName, mbd, filteredPds, pvs); }

 }

//将属性应用到bean中 

//将所有ProtertyValues中的属性填充至BeanWrapper中。

 applyPropertyValues(beanName, mbd,bw, pvs); 

}

我们详细分析下populateBean的流程:

(1)首先进行属性是否为空的判断

(2)通过调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)方法来控制程序是否继续进行属性填充

(3)根据注入类型(byName/byType)提取依赖的bean,并统一存入PropertyValues中

(4)应用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName)方法,对属性获取完毕填充前的再次处理,典型的应用是RequiredAnnotationBeanPostProcesser类中对属性的验证

(5)将所有的PropertyValues中的属性填充至BeanWrapper中

上面步骤中有几个地方是我们比较感兴趣的,它们分别是依赖注入(autowireByName/autowireByType)以及属性填充,接下来进一步分析这几个功能的实现细节

自动注入

Spring 会根据注入类型( byName / byType )的不同,调用不同的方法(autowireByName() / autowireByType())来注入属性值。

autowireByName()

protectedvoid autowireByName(String beanName, AbstractBeanDefinition mbd,BeanWrapper bw, MutablePropertyValues pvs) {

 // 获取Bean 对象中非简单属性

String[] propertyNames = unsatisfiedNonSimpleProperties(mbd,bw);

for (String propertyName : propertyNames) { 

// 如果容器中包含指定名称的bean,则将该 bean 注入到bean中

if(containsBean(propertyName)) { 

// 递归初始化相关beanObjectbean = 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");}

 } 

}

}

该方法逻辑很简单,获取该 bean 的非简单属性,什么叫做非简单属性呢?就是类型为对象类型的属性,但是这里并不是将所有的对象类型都都会找到,比如 8 个原始类型,String 类型 ,Number类型、Date类型、URL类型、URI类型等都会被忽略,如下:

protectedString[] unsatisfiedNonSimpleProperties(AbstractBeanDefinitionmbd,BeanWrapperbw) {

Set result =newTreeSet<>();

PropertyValuespvs=mbd.getPropertyValues();

PropertyDescriptor[]pds=bw.getPropertyDescriptors();

for(PropertyDescriptorpd : pds) {

if(pd.getWriteMethod() !=null&& !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) {result.add(pd.getName());

}

}

returnStringUtils.toStringArray(result);

}

这里获取的就是需要依赖注入的属性。

autowireByName()函数的功能就是根据传入的参数中的pvs中找出已经加载的bean,并递归实例化,然后加入到pvs中

autowireByType

autowireByType与autowireByName对于我们理解与使用来说复杂程度相似,但是实现功能的复杂度却不一样,我们看下方法代码:

protectedvoidautowireByType(StringbeanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  TypeConverter converter = getCustomTypeConverter();

if(converter ==null) { 

converter = bw;

Set autowiredBeanNames =newLinkedHashSet(4);

//寻找bw中需要依赖注入的属性

String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

for(StringpropertyName : 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())) {

//探测指定属性的set方法

MethodParameter methodParam = BeanUtils.

getWriteMethodParameter(pd);

// Do not allow eager init for type matching in case of a prioritized post-processor. booleaneager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); 

DependencyDescriptor desc =newAutowireByTypeDependencyDescriptor(methodParam, eager);

//解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowiredBeanNames中,

ObjectautowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);

if(autowiredArgument !=null) { 

pvs.add(propertyName, autowiredArgument); 

}for(StringautowiredBeanName : 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) {

thrownewUnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); 

}

}

根据名称第一步与根据属性第一步都是寻找bw中需要依赖注入的属性,然后遍历这些属性并寻找类型匹配的bean,其中最复杂就是寻找类型匹配的bean。spring中提供了对集合的类型注入支持,如使用如下注解方式:

@AutowiredprivateList tests;

这种方式spring会把所有与Test匹配的类型找出来并注入到tests属性中,正是由于这一因素,所以在autowireByType函数,新建了局部遍历autowireBeanNames,用于存储所有依赖的bean,如果只是对非集合类的属性注入来说,此属性并无用处。

对于寻找类型匹配的逻辑实现是封装在了resolveDependency函数中,其实现如下:

publicObjectresolveDependency(DependencyDescriptor descriptor,StringbeanName, Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

if(descriptor.getDependencyType().equals(ObjectFactory.class)) {

//ObjectFactory类注入的特殊处理

returnnewDependencyObjectFactory(descriptor, beanName); 

}else if(descriptor.getDependencyType().equals(javaxInjectProviderClass)) {

//javaxInjectProviderClass类注入的特殊处理

returnnewDependencyProviderFactory().createDependencyProvider(descriptor, beanName); 

}else{

//通用处理逻辑

returndoResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter); 

}

}

protectedObjectdoResolveDependency(DependencyDescriptor descriptor, Classtype,StringbeanName,  Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException

 {/*

* 用于支持Spring中新增的注解@Value

*/

Objectvalue = getAutowireCandidateResolver().getSuggestedValue(descriptor);

if(value !=null) {

if(valueinstanceofString) {

StringstrVal = resolveEmbeddedValue((String) value); 

BeanDefinition bd = (beanName !=null&& containsBean(beanName) ? getMergedBeanDefinition(beanName) :null); 

value = evaluateBeanDefinitionString(strVal, bd); 

TypeConverter converter = (typeConverter !=null? typeConverter : getTypeConverter());

return(descriptor.getField() !=null?  converter.convertIfNecessary(value,type, descriptor.getField()) :  converter.convertIfNecessary(value,type, descriptor.getMethodParameter()));

  }

//如果解析器没有成功解析,则需要考虑各种情况 //属性是数组类型

if(type.isArray()) { 

Class componentType =type.getComponentType();

//根据属性类型找到beanFactory中所有类型的匹配bean,

//返回值的构成为:key=匹配的beanName,value=beanName对应的实例化后的bean(通过getBean(beanName)返回)

Map matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);

if(matchingBeans.isEmpty()) {

//如果autowire的require属性为true而找到的匹配项却为空则只能抛出异常

if(descriptor.isRequired()) { 

raiseNoSuchBeanDefinitionException(componentType,"array of "+ componentType.getName(), descriptor);  }

returnnull; 

}

if(autowiredBeanNames !=null) {

  autowiredBeanNames.addAll(matchingBeans.keySet()); 

TypeConverter converter = (typeConverter !=null? typeConverter : getTypeConverter());

//通过转换器将bean的值转换为对应的type类型

returnconverter.convertIfNecessary(matchingBeans.values(),type); 

}

//属性是Collection类型

else  if(Collection.class.isAssignableFrom(type) &&type.isInterface()) { 

Class elementType = descriptor.getCollectionType();

if(elementType ==null) {

if(descriptor.isRequired()) {

thrownewFatalBeanException("No element type declared for collection ["+type.getName() +"]");  }returnnull; 

Map matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);

if(matchingBeans.isEmpty()) {

if(descriptor.isRequired()) { 

raiseNoSuchBeanDefinitionException(elementType,"collection of "+ elementType.getName(), descriptor); 

}

returnnull; 

}

if(autowiredBeanNames !=null) { 

autowiredBeanNames.addAll(matchingBeans.keySet()); 

TypeConverter converter = (typeConverter !=null? typeConverter :

getTypeConverter());returnconverter.convertIfNecessary(matchingBeans.values(),type);  }

//属性是Map类型

elseif(Map.class.isAssignableFrom(type) &&type.isInterface()) { 

Class keyType = descriptor.getMapKeyType();if(keyType ==null|| !String.class.isAssignableFrom(keyType)) {

if(descriptor.isRequired()) {thrownewFatalBeanException("Key type ["+ keyType +"] of map ["+type.getName() +"] must be assignable to [java.lang.String]"); 

}

returnnull; 

Class valueType = descriptor.getMapValueType();

if(valueType ==null) {if(descriptor.isRequired()) {

thrownewFatalBeanException("No value type declared for map ["+type.getName() +"]");  }returnnull; 

Map matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);

if(matchingBeans.isEmpty()) {

if(descriptor.isRequired()) { 

raiseNoSuchBeanDefinitionException(valueType,"map with value type "+ valueType.getName(), descriptor); 

}returnnull; 

}

if(autowiredBeanNames !=null) { 

autowiredBeanNames.addAll(matchingBeans.keySet()); 

}

returnmatchingBeans; 

}else{ 

Map matchingBeans = findAutowireCandidates(beanName,type, descriptor);

if(matchingBeans.isEmpty()) {

if(descriptor.isRequired()) { 

raiseNoSuchBeanDefinitionException(type,"", descriptor);  }returnnull; 

}

if(matchingBeans.size() >1) {StringprimaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);

if(primaryBeanName ==null) {

thrownewNoUniqueBeanDefinitionException(type, matchingBeans.keySet()); 

}

if(autowiredBeanNames !=null) {  autowiredBeanNames.add(primaryBeanName); 

}

returnmatchingBeans.get(primaryBeanName); 

}

// We have exactly one match. Map.Entry entry = matchingBeans.entrySet().iterator().next();if(autowiredBeanNames !=null) {  autowiredBeanNames.add(entry.getKey()); 

}

//已经确定只有一个匹配项 returnentry.getValue(); 

}

}

applyPropertyValues

程序运行到这里,已经完成了对所有注入属性的获取,但是获取的属性是以PropertyValues形式存在的,还并没有应用到已经实例化的bean中,这一工作是在applyPropertyValues中。继续跟踪到方法体中:

protectedvoidapplyPropertyValues(StringbeanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {

if(pvs ==null|| pvs.isEmpty()) {

return; 

MutablePropertyValues mpvs =null; 

List original;

if(System.getSecurityManager() !=null) {

if(bwinstanceofBeanWrapperImpl) { 

((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); 

}

if(pvsinstanceofMutablePropertyValues) { 

mpvs = (MutablePropertyValues) pvs;

//如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanwapper中

if(mpvs.isConverted()) {

// Shortcut: use the pre-converted values as-is. try{ 

bw.setPropertyValues(mpvs);

return; 

}

catch(BeansException ex) {

thrownewBeanCreationException(  mbd.getResourceDescription(), beanName,"Error setting property values", ex); 

original = mpvs.getPropertyValueList();  }

else{

//如果pvs并不是使用MutablePropertyValues封装的类型,那么直接使用原始的属性获取方法

original = Arrays.asList(pvs.getPropertyValues()); 

TypeConverter converter = getCustomTypeConverter();

if(converter ==null) { 

converter = bw;  }

//获取对应的解析器 BeanDefinitionValueResolver valueResolver =newBeanDefinitionValueResolver(this, beanName, mbd, converter);

// Create a deep copy, resolving any references for values. List deepCopy =newArrayList(original.size());booleanresolveNecessary =false;

//遍历属性,将属性转换为对应类的对应属性的类型

for(PropertyValue pv : original) {

if(pv.isConverted()) {  deepCopy.add(pv); 

}else{

StringpropertyName = pv.getName();

ObjectoriginalValue = pv.getValue();

ObjectresolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

ObjectconvertedValue = resolvedValue;booleanconvertible = 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 && originalValueinstanceofTypedStringValue &&  !((TypedStringValue) originalValue).isDynamic() &&  !(convertedValueinstanceofCollection || ObjectUtils.isArray(convertedValue))) { 

pv.setConvertedValue(convertedValue); 

deepCopy.add(pv);

  }else{ 

resolveNecessary =true; 

deepCopy.add(newPropertyValue(pv, convertedValue)); 

}

if(mpvs !=null&& !resolveNecessary) { 

mpvs.setConverted(); 

}

// Set our (possibly massaged) deep copy. try{  bw.setPropertyValues(newMutablePropertyValues(deepCopy)); 

}

catch(BeansException ex) {

thrownewBeanCreationException(  mbd.getResourceDescription(), beanName,"Error setting property values", ex); 

}

}

我们来看看具体的属性赋值过程

publicclassMyTestBean{privateString name ;

publicMyTestBean(String name){

this.name = name; }publicMyTestBean(){ }

publicStringgetName(){

returnname;

}

publicvoidsetName(String name){

this.name = name; }

}

如上 bw.setPropertyValues 最终都会走到如下方法

@Overridepublic void setValue(final @Nullable Object value) throws Exception {

//获取writeMethod,也就是我们MyTestBean的setName方法

final Method writeMethod = (this.pdinstanceofGenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor)this.pd).getWriteMethodForActualAccess() :this.pd.getWriteMethod());

if(System.getSecurityManager() !=null) {

AccessController.doPrivileged((PrivilegedAction<Object>)()->{ ReflectionUtils.makeAccessible(writeMethod);returnnull; });

try{ AccessController.doPrivileged((PrivilegedExceptionAction<Object>)()->writeMethod.invoke(getWrappedInstance(), value), acc);

}catch(PrivilegedActionException ex) {throwex.getException(); }

}else{ ReflectionUtils.makeAccessible(writeMethod);

//通过反射调用方法进行赋值 writeMethod.invoke(getWrappedInstance(), value);

}

}

Debug如下

就是利用反射进行调用对象的set方法赋值

至此,doCreateBean() 第二个过程:属性填充 已经分析完成了,下篇分析第三个过程:循环依赖的处理,其实循环依赖并不仅仅只是在 doCreateBean() 中处理,其实在整个加载 bean 的过程中都有涉及,所以下篇内容并不仅仅只局限于 doCreateBean()。

相关文章

网友评论

      本文标题:spring源码深度解析—IOC 之属性填充

      本文链接:https://www.haomeiwen.com/subject/licfkctx.html