spring源码---DI:populate()

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中的Property
   PropertyValues 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);
     //注入属性 通过name
      if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
      // 注入属性 通过type
      if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
   }
    //同样 测试demo中, 两个都是false
   boolean 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());
   }
   //根据用户自定义的类型转换 ,没有定义就为null
   TypeConverter 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) {//true
            convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         //存储转换后的属性值,避免每次属性注入时的转换工作
         if (resolvedValue == originalValue) {//false
            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. 进行属性的依赖注入
      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 { //没有获取到数组的类型,也没有获取到数组元数的类型,直接设置为Object
            elementType = 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)); //this
      if (nestedPa == this) { //true
         pv.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()) { //false
               try {
                  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);
		}
	}

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值