Spring(十四):继续创建单例Bean,提前曝光,linux基础及应用教程梁如军答案

Spring(十四):继续创建单例Bean,提前曝光,linux基础及应用教程梁如军答案,第1张

Spring(十四):继续创建单例Bean,提前曝光,linux基础及应用教程梁如军答案

//判断后继处理器是否已经初始化

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

//判断是否需要依赖检查

boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;

if (hasInstAwareBpps) {

//如果后继处理器已经初始化完成

if (pvs == null) {

pvs = mbd.getPropertyValues();

}

//

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {

PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

if (pvsToUse == null) {

if (filteredPds == null) {

filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

}

//对所有需要依赖检查的属性进行后处理,但此时还没有依赖检查

pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

if (pvsToUse == null) {

return;

}

}

pvs = pvsToUse;

}

}

//如果需要类型检查

if (needsDepCheck) {

if (filteredPds == null) {

filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

}

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

checkDependencies(beanName, mbd, filteredPds, pvs);

}

if (pvs != null) {

//将属性应用到bean中

applyPropertyValues(beanName, mbd, bw, pvs);

}

}

总结一下populateBan方法的作用

  • 调用InstantiationAwareBeanPostPostProcessor处理器的postProcessAfterInstantiation函数

  • 根据注入的类型,byType或者byName来提取依赖的bean,并且统一存入PropertyValues中去

  • 应用InstantiatinAwareBeanPostProcessor处理的postProcessPropertyValues的方法,对注入的属性再次处理

  • 将找到的属性填充至BeanWrapper中,也就是PropertyValues中去

这里比较重点的就是第二和第四步的注入,其他感觉太难了,看不下去。。。

根据注入的类型进行提取依赖bean

注入的类型有两种

  • byType

  • byName

我们可以给bean去设置注入的类型

这里的自动注入是对依赖的bean进行自动注入,而不是本身。。。

对应的代码为如下

AUTOWIRE_BY_NAME

这是根据名字进行自动注入的方法,也就是依赖的name属性

源码如下

protected void autowireByName(

String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

//获取需要注入的依赖属性,注意这里是获取不是简单类型的,也就是基本数据类型

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

//遍历这些依赖属性

for (String propertyName : propertyNames) {

//判断Spring的IOC容器中是不是存在这个bean

//可以看出这就是ByName形式

if (containsBean(propertyName)) {

//调用getBean方法进行创建

//看到这就懂了,单例的时候是怎么递归创建依赖的

//并且怎么去检测循环依赖的

Object bean = getBean(propertyName);

//将生成的bean添加新PropertyValues中

pvs.add(propertyName, bean);

//进行注册该bean

registerDependentBean(propertyName, beanName);

if (logger.isTraceEnabled()) {

logger.trace(“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”);

}

}

}

}

步骤大概如下

  • 获取需要依赖的属性

  • 遍历需要依赖的属性

  • 根据依赖的属性的beanName查看IOC容器里面是否有该bean,体现出了ByName

  • 如果不存在该bean,抛错,表示没有找到匹配的bean

  • 如果存在该bean,调用getBean方法去创建依赖的bean(又走那一套流程,所以说到底创建bean就是一个递归过程)

  • 将创建好的bean放入PropertyValues中

  • 对该bean进行注册

整体逻辑没什么,下面来看是如何获取依赖的属性的

unsatisfiedNonSimpleProperties

对应获取依赖的属性具体方法在这里,这个方法会主动排除简单属性,即引用类型和基本数据类型

源码如下

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {

//创建一个treeSet进行去重

Set result = new TreeSet<>();

//获取所有的依赖

PropertyValues pvs = mbd.getPropertyValues();

PropertyDescriptor[] pds = bw.getPropertyDescriptors();

//

for (PropertyDescriptor pd : pds) {

//只有写了set方法

//不在不检查依赖的集合中

//不是简单类型

if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&

!BeanUtils.isSimpleProperty(pd.getPropertyType())) {

//满足条件之后添加进里面

result.add(pd.getName());

}

}

return StringUtils.toStringArray(result);

}

看代码比较抽象,所以决定举个栗子

配置文件只是简单的一个注入类型

类也很简单,只是简单地提供了一个set方法注入

下面我们直接看那两个集合是什么

PropertyDescriptor[] pds = bw.getPropertyDescriptors();

结果如下

里面有两个对象

一个是bean自己的class,没有writeMethod

另外一个,关于twoPojo的,而且里面存称了writeMethod正式set方法!!!!

所以可以推测这个集合获取的是需要依赖的属性详情

PropertyValues pvs = mbd.getPropertyValues();

里面的东西如下所示

可以看到,里面完全就是配置文件里面的信息。。。。

所以,这个集合里面存储的是配置文件里面的依赖属性的信息

那么现在,这个for循环来剔除什么,就很容易看出了

回归到我们的for循环

for (PropertyDescriptor pd : pds) {

//只有写了set方法

//不在不检查依赖的集合中

//不是简单类型

//并且配置文件里面没有这个beanName,

//如果配置文件里有那就去IOC容器里面拿就好了,不需要自动注入

//而不是采用注入的方式

if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&

!BeanUtils.isSimpleProperty(pd.getPropertyType())) {

//满足条件之后添加进里面

result.add(pd.getName());

}

}

可以看到结果,result为0

假如我们去掉配置文件的property

可以看到结果带上了twoPOJO

下面再来看一下BeanUtils过滤了什么东西出来

可以看到其过滤一些类型

  • void类型

  • isPrimitiveOrWrapper:判断是不是包装类,也就是过滤包装类

  • Enum类型

  • Date类型

  • URI类型

  • URL类型

  • Locale类型

  • Class类型

  • CharSequence类型

总结一下哪种依赖bean会被

  • 没有写Set方法的依赖会被过滤

  • 位于不进行检查的集合中依赖会被过滤

  • 配置文件中已经指定注入的类型会被过滤

  • 属于简单类型的也会被过滤

AUTOWIRE_BY_TYPE

还有一种自动注入类型就是根据类型去寻找

对应的代码如下

对应的方法是autowireByType

源码如下

protected void autowireByType(

String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

//获取类型处理器

TypeConverter converter = getCustomTypeConverter();

if (converter == null) {

converter = bw;

}

//使用一个linkedHashSet来存储需要自动注入的bean的beanName

//之前存储beanName也是使用一个set进行去重,然后转化成一个字符串数组

Set autowiredBeanNames = new linkedHashSet<>(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.

//判断该依赖是不是Object类型,(注意:过滤并没有将Object类型过滤)

if (Object.class != pd.getPropertyType()) {

//获取该bean的set方法的参数。。

//相当于就是获取类型了。。体现出了ByType

MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);

// Do not allow eager init for type matching in case of a prioritized post-processor.

boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);

DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

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

Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);

if (autowiredArgument != null) {

pvs.add(propertyName, autowiredArgument);

}

//遍历需要注入的bean

for (String autowiredBeanName : autowiredBeanNames) {

//注册依赖

registerDependentBean(autowiredBeanName, beanName);

if (logger.isTraceEnabled()) {

logger.trace(“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);

}

}

}

从这里可以看到两个细节

  • Spring对于Object类型的,使用ByType是不会进行注入的

  • 获取类型是通过过去Set方法的参数来实现的,参数其实就是Type了,可以看出是ByType的体现

  • 通过resolveDependency来进行创建依赖

resolveDependency

可以看到,对ByType的依赖进行创建是交由DefaultListableBeanFactory来实现的,而ByName的依赖进行创建交由AbstractAutowireCapableFactory来实现的

源码如下

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,

@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

//

descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

//扩展了对Optional类的支持

if (Optional.class == descriptor.getDependencyType()) {

//Optional类单独使用方法创建

return createOptionalDependency(descriptor, requestingBeanName);

}

//对于ObjectFactory和ObjectProvider也是单独方法创建

else if (ObjectFactory.class == descriptor.getDependencyType() ||

ObjectProvider.class == descriptor.getDependencyType()) {

return new DependencyObjectProvider(descriptor, requestingBeanName);

}

//对JavaInjectProviderClass进行单独处理

else if (javaxInjectProviderClass == descriptor.getDependencyType()) {

return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);

}

else {

//对于其他一般类型

//使用AutowireCandidateResolver来进行注入

Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(

descriptor, requestingBeanName);

if (result == null) {

//如果AutpwireCandidateResolver注入失败,使用doResolveDependency进行注入

result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

}

return result;

}

}

可以看到,对于一些特定类型单独处理之外,其他的类型都会走相同的步骤(大部分)

getLazyResollutionProxyIfNecessary

对于一般类型,首先会经过这个方法进行处理

从这个方法的注释来看,感觉像是对切入点进行添加代理的。。

不过其默认实现直接返回Null,那就先不看了。

doResolveDependency

接下来执行这个方法进行处理

源码如下,可以看到十分恐怖。。。

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,

@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

try {

Object shortcut = descriptor.resolveShortcut(this);

if (shortcut != null) {

return shortcut;

}

//获取类对象,也就是前面通过set方法拿到的参数

Class type = descriptor.getDependencyType();

//支持新增的@Value注解

//@Value注解是可以直接用在类上的,所以这里是根据类获取其注解

//然后去相应配置中进行注入

Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);

//判断是不是@Value注入了

//所以ByName不会被@Value注入????

if (value != null) {

//如果是,会执行下面这些 *** 作

if (value instanceof String) {

String strVal = resolveEmbeddedValue((String) value);

BeanDefinition bd = (beanName != null && containsBean(beanName) ?

getMergedBeanDefinition(beanName) : null);

value = evaluateBeanDefinitionString(strVal, bd);

}

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

try {

return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());

}

catch (UnsupportedOperationException ex) {

// A custom TypeConverter which does not support TypeDescriptor resolution…

return (descriptor.getField() != null ?

converter.convertIfNecessary(value, type, descriptor.getField()) :

converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));

}

}

//考虑这个属性是不是多个Bean的,也就是处理集合类型

Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

if (multipleBeans != null) {

return multipleBeans;

}

//查找出所有的候选者

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

if (matchingBeans.isEmpty()) {

if (isRequired(descriptor)) {

raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

}

return null;

}

String autowiredBeanName;

Object instanceCandidate;

//判断候选者的数量

if (matchingBeans.size() > 1) {

//如果存在两个或两个意思,执行下面 *** 作

//决定使用哪个候选者

autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);

//判断是否可以决定出来

if (autowiredBeanName == null) {

//

if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {

return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);

}

else {

// In case of an optional Collection/Map, silently ignore a non-unique case:

// possibly it was meant to be an empty collection of multiple regular beans

// (before 4.3 in particular when we didn’t even look for collection beans).

return null;

}

}

instanceCandidate = matchingBeans.get(autowiredBeanName);

}

else {

//如果只有一个候选值,进行下面处理

// We have exactly one match.

//去获取唯一的一个候选者

Map.Entry entry = matchingBeans.entrySet().iterator().next();

//使用候选者的属性

//beanName为key

//依赖的对象就是候选者的value

autowiredBeanName = entry.getKey();

instanceCandidate = entry.getValue();

}

//添加进集合

if (autowiredBeanNames != null) {

autowiredBeanNames.add(autowiredBeanName);

}

if (instanceCandidate instanceof Class) {

instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);

}

//此时让result为得出来的候选者

Object result = instanceCandidate;

//再判断是不是NullBean类型

if (result instanceof NullBean) {

if (isRequired(descriptor)) {

raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

}

result = null;

}

if (!ClassUtils.isAssignablevalue(type, result)) {

throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());

}

//返回结果

return result;

}

finally {

ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);

}

}

好复杂,看的要吐了。。。。。。

总结一下大概的过程

  • 通过前面解析set方法得到的参数来获取Class类型

  • 通过这个Class类型去判断其有没有被@Value注解标识

  • 如果有,走另一个逻辑

  • 如果没有,代表还是需要去注入

  • 判断是不是集合类型的,如果是集合类型的,又走集合类型的处理

  • 如果不是集合类型的,去获取所有候选者

  • 判断候选者的数量

  • 如果候选者数量存在两个以上

  • 判断决定使用哪个候选者,如果决定不出来又是另外一个方法

  • 如果决定出来了,该候选者就是依赖Bean的实例了

  • 如果候选者只有一个,直接使用该候选者

  • 然后对产生出来的候选者做一些判空处理

  • 返回结果

大概的思路就是这样。。。。下次再仔细研究,这太难了

到了这里之后,我们就已经完成了对所有注入属性的获取,但是获取了属性是以PropertyValue形式存在的,还没有应用到已经实例化的bean中

注入属性

回到populate方法中,现在所有的依赖就已经创建好了,等待注入bean里面了,对应的执行的方法为applyPropertyValues方法,同时也是populateBean最后的执行方法

源码如下

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

//如果依赖为空直接返回

if (pvs.isEmpty()) {

return;

}

if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {

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

}

MutablePropertyValues mpvs = null;

List original;

if (pvs instanceof MutablePropertyValues) {

mpvs = (MutablePropertyValues) pvs;

//判断依赖是不是已经转化为对应的类型

if (mpvs.isConverted()) {

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

try {

//如果转化成对应的类型,直接装入BeanWrapper中

bw.setPropertyValues(mpvs);

//结束返回

return;

}

catch (BeansException ex) {

throw new BeanCreationException(

mbd.getResourceDescription(), beanName, “Error setting property values”, ex);

}

}

original = mpvs.getPropertyValueList();

}

else {

//将依赖放进original中

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.

//使用一个ArrayList去存储依赖的深拷贝对象

List deepCopy = new ArrayList<>(original.size());

boolean resolveNecessary = false;

//遍历所有依赖

for (PropertyValue pv : original) {

//判断依赖是不是已经转换过了

if (pv.isConverted()) {

//如果转换过了就直接添加进集合中去

deepCopy.add(pv);

}

else {

//获取依赖的名字,变量名

String propertyName = pv.getName();

//获取依赖的值,此时已经是一个对象了

Object originalValue = pv.getValue();

//如果值是AutowiredPropertyMarker…

//不太清楚这什么情况

if (originalValue == AutowiredPropertyMarker.INSTANCE) {

Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();

if (writeMethod == null) {

throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);

}

originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);

}

//使用解析器进行解析

Object resolvedValue = valueResolver.resolvevalueIfNecessary(pv, originalValue);

//将解析结果放在convertedValue变量中

Object convertedValue = resolvedValue;

boolean convertible = bw.isWritableProperty(propertyName) &&

!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);

if (convertible) {

//进行转化

convertedValue = convertForProperty(resolved

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

Value, 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);

}

}

注入属性也好难懂,大体的过程是

  • 判断依赖是不是都转化好了

  • 如果都转化好了就直接添加进去beanWrapper中

  • 如果没有转化好,就要进行对依赖深拷贝了

  • 获取依赖的变量名和依赖的值,值通常是一个Spring自定义的RuntimeBeanReference

  • 使用解析器进行转化

  • 将转化后的值添加进去deepCopy集合中,deepCopy是一个ArrayList

  • 最后将deepCopy集合存进beanWrapper中

所以,重点的部分在于解析和将解析后依赖存进beanWrapper这里,下面看看是如何进行解析的

valueResolver.resolvevalueIfNecessary(pv, originalValue);

这个方法就是进行解析的

源码如下

@Nullable

public Object resolvevalueIfNecessary(Object argName, @Nullable Object value) {

// We must check each value to see whether it requires a runtime reference

// to another bean to be resolved.

//判断是不是RuntimeBeanReference

if (value instanceof RuntimeBeanReference) {

RuntimeBeanReference ref = (RuntimeBeanReference) value;

return resolveReference(argName, ref);

}

//判断是不是RuntimeBeanNameReference

else if (value instanceof RuntimeBeanNameReference) {

String refName = ((RuntimeBeanNameReference) value).getBeanName();

refName = String.valueOf(doevaluate(refName));

if (!this.beanFactory.containsBean(refName)) {

throw new BeanDefinitionStoreException(

“Invalid bean name '” + refName + "’ in bean reference for " + argName);

}

return refName;

}

//判断是不是BeanDefinitinHolder

else if (value instanceof BeanDefinitionHolder) {

// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.

BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;

return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());

}

//判断是不是BeanDefinition

else if (value instanceof BeanDefinition) {

// Resolve plain BeanDefinition, without contained name: use dummy name.

BeanDefinition bd = (BeanDefinition) value;

String innerBeanName = “(inner bean)” + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +

ObjectUtils.getIdentityHexString(bd);

return resolveInnerBean(argName, innerBeanName, bd);

}

//判断是不是DependencyDescriptor

else if (value instanceof DependencyDescriptor) {

Set autowiredBeanNames = new linkedHashSet<>(4);

Object result = this.beanFactory.resolveDependency(

(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);

for (String autowiredBeanName : autowiredBeanNames) {

if (this.beanFactory.containsBean(autowiredBeanName)) {

this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);

}

}

return result;

}

//判断是不是ManagedArray

else if (value instanceof ManagedArray) {

// May need to resolve contained runtime references.

ManagedArray array = (ManagedArray) value;

Class elementType = array.resolvedElementType;

if (elementType == null) {

String elementTypeName = array.getElementTypeName();

if (StringUtils.hasText(elementTypeName)) {

try {

elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());

array.resolvedElementType = elementType;

}

catch (Throwable ex) {

// Improve the message by showing the context.

throw new BeanCreationException(

this.beanDefinition.getResourceDescription(), this.beanName,

"Error resolving array type for " + argName, ex);

}

}

else {

elementType = Object.class;

}

}

return resolveManagedArray(argName, (List) value, elementType);

}

//判断是不是ManagedList

else if (value instanceof ManagedList) {

// May need to resolve contained runtime references.

return resolveManagedList(argName, (List) value);

}

//判断是不是ManagedSet

else if (value instanceof ManagedSet) {

// May need to resolve contained runtime references.

return resolveManagedSet(argName, (Set) value);

}

//判断是不是ManagedMap

else if (value instanceof ManagedMap) {

// May need to resolve contained runtime references.

return resolveManagedMap(argName, (Map) value);

}

//判断是不是ManagedProperties

else if (value instanceof ManagedProperties) {

Properties original = (Properties) value;

Properties copy = new Properties();

original.forEach((propKey, propValue) -> {

if (propKey instanceof TypedStringValue) {

propKey = evaluate((TypedStringValue) propKey);

}

if (propValue instanceof TypedStringValue) {

propValue = evaluate((TypedStringValue) propValue);

}

if (propKey == null || propValue == null) {

throw new BeanCreationException(

this.beanDefinition.getResourceDescription(), this.beanName,

"Error converting Properties key/value pair for " + argName + “: resolved to null”);

}

copy.put(propKey, propValue);

});

return copy;

}

//判断是不是TypeStringValue

else if (value instanceof TypedStringValue) {

// Convert value to target type here.

TypedStringValue typedStringValue = (TypedStringValue) value;

Object valueObject = evaluate(typedStringValue);

try {

Class resolvedTargetType = resolveTargetType(typedStringValue);

if (resolvedTargetType != null) {

return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);

}

else {

return valueObject;

}

}

catch (Throwable ex) {

// Improve the message by showing the context.

throw new BeanCreationException(

this.beanDefinition.getResourceDescription(), this.beanName,

"Error converting typed String value for " + argName, ex);

}

}

//判断是不是NullBean

else if (value instanceof NullBean) {

return null;

}

//如果都不是上述类型

else {

return evaluate(value);

}

}

可以看到,这里注入属性根据传进来的值是什么类型做了区分处理

  • RuntimeBeanReference类型的

  • RuntimeBeanNameReference类型的

  • BeanDefinitionHolder类型的

  • BeanDefiniton类型的

  • DependencyDescriptor类型的

  • ManagedArray类型的

  • ManagedList类型的额

  • ManagedSet类型的

  • ManagedMap类型的

  • ManagedProperty类型的

  • NullBean类型的

  • 其他类型,这里的其他类型已经就是对应的class类型了

一般传进来的是一个已经是对应的类型了

那就会直接对应最后的evaluate方法

源码如下

@Nullable

protected Object evaluate(@Nullable Object value) {

//对字符串进行处理

//主要的处理是将字符串解析为一个Bean对象

if (value instanceof String) {

return this.doevaluate((String)value);

}

//对字符串数组进行处理

else if (value instanceof String[]) {

String[] values = (String[])((String[])value);

boolean actuallyResolved = false;

Object[] resolvedValues = new Object[values.length];

//其实就是遍历字符串数组,对每个字符串进行处理

for(int i = 0; i < values.length; ++i) {

String originalValue = values[i];

Object resolvedValue = this.doevaluate(originalValue);

if (resolvedValue != originalValue) {

actuallyResolved = true;

}

resolvedValues[i] = resolvedValue;

}

return actuallyResolved ? resolvedValues : values;

}

//不是字符串也不是字符串数组,直接返回value,也就是创建好的对象

//一般直接在这里就返回了

else {

return value;

}

}

可以看到这个方法对字符串和字符串数组做了特殊处理,但这里是不可能出现String类型和字符串数组类型的。。。因为前面已经过滤掉了

bw.setPropertyValues

这个方法就是将依赖存进beanWrapper中了

可以看到,此时要注入的依赖都存进了deepCopy中

进来这个方法之后,可以看到这个方法是交由AbstractPropertyAccessor实现的,并且调用了重载方法

源码如下

@Override

public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)

throws BeansException {

//存储异常的

List propertyAccessExceptions = null;

//将传进来的依赖转为List

List propertyValues = (pvs instanceof MutablePropertyValues ?

((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));

//这个参数为false,不考虑下面这步

if (ignoreUnknown) {

this.suppressNotWritablePropertyException = true;

}

try {

//遍历传进来的所有依赖

for (PropertyValue pv : propertyValues) {

// setPropertyValue may throw any BeansException, which won’t be caught

// here, if there is a critical failure such as no matching field.

// We can attempt to deal only with less serious exceptions.

try {

//进行注入

setPropertyValue(pv);

}

//下面都是捕捉异常处理,不看了

catch (NotWritablePropertyException ex) {

if (!ignoreUnknown) {

throw ex;

}

// Otherwise, just ignore it and continue…

}

catch (NullValueInNestedPathException ex) {

if (!ignoreInvalid) {

throw ex;

}

// Otherwise, just ignore it and continue…

}

//统计PropertyAccessException异常

catch (PropertyAccessException ex) {

if (propertyAccessExceptions == null) {

propertyAccessExceptions = new ArrayList<>();

}

propertyAccessExceptions.add(ex);

}

}

}

finally {

if (ignoreUnknown) {

this.suppressNotWritablePropertyException = false;

}

}

//这里是统计出现的PropertyAccessException

//最后全部抛出

// If we encountered individual exceptions, throw the composite exception.

if (propertyAccessExceptions != null) {

PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);

throw new PropertyBatchUpdateException(paeArray);

}

}

可以看出这个方法是遍历所有的依赖,然后给每个依赖去执行setProperty方法,关键在于setProperty方法

点进来之后,你会发现IDEA会跳到这里来

但其实这个方法被AbstractNestablePropertyAccessor给重写了!!! 所以执行的不是这里的逻辑,这里是不会进来的(上当了)

所以我们应该从这里点击进去,才能继续断点调试

这个方法的源码如下

@Override

public void setPropertyValue(PropertyValue pv) throws BeansException {

PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;

//判断有没有token,一般的注入都不会进来这里

if (tokens == null) {

String propertyName = pv.getName();

AbstractNestablePropertyAccessor nestedPa;

try {

nestedPa = getPropertyAccessorForPropertyPath(propertyName);

}

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

}

else {

//一般注入会进来这里

setPropertyValue(tokens, pv);

}

}

进来之后就是另外一个重载的方法

protected void setPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {

//这个tokens.key一般也是为0

if (tokens.keys != null) {

this.processKeyedProperty(tokens, pv);

} else {

//所以一般是进来这个方法

this.processLocalProperty(tokens, pv);

}

}

processLocalProperty

该方法的源码如下

private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {

//根据tokens的actualName获取注入依赖的信息

//比如之前的beanWrapper、一些Class信息

//可以理解成ph此时就是要被注入依赖的bean

PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);

if (ph == null || !ph.isWritable()) {

if (pv.isOptional()) {

if (logger.isDebugEnabled()) {

logger.debug(“Ignoring optional value for property '” + tokens.actualName +

“’ - property not found on bean class [” + getRootClass().getName() + “]”);

}

return;

}

if (this.suppressNotWritablePropertyException) {

// Optimization for common ignoreUnknown=true scenario since the

// exception would be caught and swallowed higher up anyway…

return;

}

throw createNotWritablePropertyException(tokens.canonicalName);

}

Object oldValue = null;

try {

//获取依赖的value,此时是一个对象

Object originalValue = pv.getValue();

Object valueToApply = originalValue;

if (!Boolean.FALSE.equals(pv.conversionNecessary)) {

if (pv.isConverted()) {

valueToApply = pv.getConvertedValue();

}

else {

if (isExtractOldValueForEditor() && ph.isReadable()) {

try {

oldValue = ph.getValue();

}

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 + tokens.canonicalName + “’”, ex);

}

}

}

valueToApply = convertForProperty(

tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());

}

pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);

}

//对bean进行注入依赖

ph.setValue(valueToApply);

}

catch (TypeMismatchException ex) {

throw ex;

}

catch (InvocationTargetException ex) {

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5660987.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存