当前位置: 代码迷 >> 综合 >> spring源码---DI:populate()
  详细解决方案

spring源码---DI:populate()

热度:21   发布时间:2024-02-08 12:14:35.0

populate()依赖注入

继续之章节的doCreateBean()方法第四流程,对bean进行依赖注入,测试用例:

<bean id="book" class="com.myProject.Myspring.Book"/>
<bean id="user" class="com.myProject.Myspring.User"><property name="book" ref="book"/>
</bean>

populate()核心代码:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {...检查//获取 配置的 属性 对应上方xml中的PropertyPropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//测试 demo中,返回的是0,所以下面的方法直接跳过int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {//深克隆MutablePropertyValues newPvs = new MutablePropertyValues(pvs);//注入属性 通过nameif (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// 注入属性 通过typeif (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}//同样 测试demo中, 两个都是falseboolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);if (hasInstAwareBpps || needsDepCheck) {... 一大堆 检查操作}if (pvs != null) { //真正 依赖注入的地方 【入】applyPropertyValues(beanName, mbd, bw, pvs);}
}

测试demo,从获得pvs开始,下面就没有调用什么方法,可以直接走到最核心的方法applyPropertyValues():

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<PropertyValue> original;if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;if (mpvs.isConverted()) { //默认是false 含义:属性值是否转化// Shortcut: use the pre-converted values as-is.try { //实例化 对象 设置属性值bw.setPropertyValues(mpvs);return;}catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}} //走这里 上面的if略过  获取属性值对象的原始类型值original = mpvs.getPropertyValueList();}else {original = Arrays.asList(pvs.getPropertyValues());}//根据用户自定义的类型转换 ,没有定义就为nullTypeConverter converter = getCustomTypeConverter();if (converter == null) { //进converter = bw;}//创建一个bean定义属性值解析器,将Bean定义中的属性值解析为bean实例对象的实际值BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);//为属性的解析值创建一个副本,将副本的数据注入实例对象// Create a deep copy, resolving any references for values.List<PropertyValue> 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(); //-----  originalValue -> resolvedValue//转换属性值,例如将引用转换为IOC容器中实例化的对象【引用】Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);//转换之后的 属性值Object convertedValue = resolvedValue;boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);if (convertible) {//trueconvertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);}//存储转换后的属性值,避免每次属性注入时的转换工作if (resolvedValue == originalValue) {//falseif (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. 进行属性的依赖注入bw.setPropertyValues(new MutablePropertyValues(deepCopy));}

该方法主要分为两种情况:

1.属性值不需要强制转换,不需要解析属性值,直接进行依赖注入

2.属性值类型需要强制转换,如对其他对象的引用等,首先需要解析属性值(demo中,依赖的是一个对象,而不是基础int数据,所以需要解析属性值,从ioc容器中获得引用),然后再进行依赖注入。

首先我们探讨BeanDefinitionValueResolver类resolveValueIfNecessary()方法:该方法内容很长

public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {//对引用类型的属性进行解析if (value instanceof RuntimeBeanReference) {RuntimeBeanReference ref = (RuntimeBeanReference) value;return resolveReference(argName, ref); //【入】} //对引用容器中另外一个bean名称的属性进行解析else if (value instanceof RuntimeBeanNameReference) {....}  //对bean类型属性的解析,主要是指bean中的内部类else if (value instanceof BeanDefinitionHolder) {BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());}else if (value instanceof BeanDefinition) {}//对集合数组类型的属性进行解析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 { //没有获取到数组的类型,也没有获取到数组元数的类型,直接设置为ObjectelementType = Object.class;}}//创建指定类型的数组return resolveManagedArray(argName, (List<?>) value, elementType);} //解析list类型的属性值else if (value instanceof ManagedList) {}else if (value instanceof ManagedSet) {}else if (value instanceof ManagedMap) {}else if (value instanceof ManagedProperties) {}else if (value instanceof TypedStringValue) {}else if (value instanceof NullBean) {return null;}else {return evaluate(value);}
}

我们的测试demo是一个普通的引用类型,所以我们调用第一个If里面的resolveReference()方法:

private Object resolveReference(Object argName, RuntimeBeanReference ref) {try {Object bean;String refName = ref.getBeanName(); //获得引用bean名称refName = String.valueOf(doEvaluate(refName));//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象if (ref.isToParent()) {if (this.beanFactory.getParentBeanFactory() == null) {throw  }bean = this.beanFactory.getParentBeanFactory().getBean(refName);}//从当前的容器中获取指定的引用bean对象,如果指定的bean没有实例化,则会递归触发引用bean的初始化和依赖注入else {bean = this.beanFactory.getBean(refName);this.beanFactory.registerDependentBean(refName, this.beanName);}if (bean instanceof NullBean) {bean = null;}return bean;}
}

解析出来需要的属性之后,我们就开始依赖注入,AbstractPropertyAccessor类setPropertyValues()方法:

public void setPropertyValues(PropertyValues pvs) throws BeansException {setPropertyValues(pvs, false, false);
}
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) {List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));for (PropertyValue pv : propertyValues) {setPropertyValue(pv);}
}

最后,各种setPropertyValue()方法,来到AbstractNestablePropertyAccessor类的setPropertyValue(token,pv)方法中:

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); //BeanWrapperImpl实例}tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); //thisif (nestedPa == this) { //truepv.getOriginalPropertyValue().resolvedTokens = tokens;}nestedPa.setPropertyValue(tokens, pv); //【入】}else {setPropertyValue(tokens, pv);}
}
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)  {if (tokens.keys != null) {processKeyedProperty(tokens, pv);}else {processLocalProperty(tokens, pv);}
}

对于我们的测试demo,走的是else,首先看一下:processKeyedProperty()方法:

private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {//调用属性的get()方法,获取属性值Object propValue = getPropertyHoldingValue(tokens); //【入】PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);String lastKey = tokens.keys[tokens.keys.length - 1];//注入array类型的属性值if (propValue.getClass().isArray()) {Class<?> requiredType = propValue.getClass().getComponentType();int arrayIndex = Integer.parseInt(lastKey);Object oldValue = null;try {if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {oldValue = Array.get(propValue, arrayIndex);}Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),requiredType, ph.nested(tokens.keys.length));int length = Array.getLength(propValue);if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {Class<?> componentType = propValue.getClass().getComponentType();Object newArray = Array.newInstance(componentType, arrayIndex + 1);System.arraycopy(propValue, 0, newArray, 0, length);setPropertyValue(tokens.actualName, newArray);propValue = getPropertyValue(tokens.actualName);}Array.set(propValue, arrayIndex, convertedValue);}}//注入list类型的属性值else if (propValue instanceof List) {}//注入map类型的属性值else if (propValue instanceof Map) {}else {throw  }
}

第二个:processLocalProperty()方法:

private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);Object oldValue = null;try {Object originalValue = pv.getValue();Object valueToApply = originalValue;if (!Boolean.FALSE.equals(pv.conversionNecessary)) {if (pv.isConverted()) {valueToApply = pv.getConvertedValue();}else {if (isExtractOldValueForEditor() && ph.isReadable()) { //falsetry {oldValue = ph.getValue();}} //valueToApply = convertForProperty(tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());}pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);}ph.setValue(valueToApply); //【注入】}
}

到此,依赖注入完成,还有一些细节,可以继续深入探讨。

紧接着,bean初始化 位于AbstractAutowireCapableBeanFactory类的initializeBean()方法,这个和spring AOP有关,所以我们在后面aop章节介绍

第六流程:如果是单例模式的,需要缓存下来

if (earlySingletonExposure) {//获取指定名称的 已注册的 单列模式的 bean对象Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) { //demo走这里exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}....
}// Register bean as disposable.
try {registerDisposableBeanIfNecessary(beanName, bean, mbd); 
}

 到这里,bean的create()结束,回到AbstractBeanFactory类的doGetbean()方法:

2.2 原型模式bean

回到AbstractBeanFactory类的doGetBean()方法中,继续我们的探索:

else if (mbd.isPrototype()) {Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args); //【入】}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

区别于单例模式,原型模式,多了before和after两个操作,都是针对属性的,中间的createBean()方法和单例模式的createBean()方法相同,所以这里就不继续展开了,我们看一下前置处理:

	protected void beforePrototypeCreation(String beanName) {Object curVal = this.prototypesCurrentlyInCreation.get();if (curVal == null) {this.prototypesCurrentlyInCreation.set(beanName); //主要是这个操作}else if (curVal instanceof String) {Set<String> beanNameSet = new HashSet<>(2);beanNameSet.add((String) curVal);beanNameSet.add(beanName);this.prototypesCurrentlyInCreation.set(beanNameSet);}else {Set<String> beanNameSet = (Set<String>) curVal;beanNameSet.add(beanName);}}

主要就是设置了一个值,其他没有动手。

  相关解决方案