//判断后继处理器是否已经初始化
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方法的依赖会被过滤
-
位于不进行检查的集合中依赖会被过滤
-
配置文件中已经指定注入的类型会被过滤
-
属于简单类型的也会被过滤
还有一种自动注入类型就是根据类型去寻找
对应的代码如下
对应的方法是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来进行创建依赖
可以看到,对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
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
//使用候选者的属性
//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) {
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)