全网最细致的spring源码分析(七):属性注入

         之前的源码阅读中,我们已经将spring创建bean的大致流程进行了了解,但大脑里依旧充满了各式各样的疑惑,这次我们更深一层去了解spring是如何进行属性注入的。

        之前在说明依赖注入的时候其实提到属性注入的方法populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw),spring保持了一贯作风,这个方法并没有实际对属性进行注入,依旧是一些前置的判断和后置的处理,既然是学习还是很有必要了解前因后果的,一起来仔细的阅读一下源码吧。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //对bean的持有对象做一个空判断,既然都到了注入属性值的时候了,持有对象肯定不可以是空的
   if (bw == null) {
        //判断RootBeanDefinition中是否有MutablePropertyValues实例,MutablePropertyValues提供了对属性的读写操作实现,同时可以通过调用构造函数进行深度拷贝
      if (mbd.hasPropertyValues()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // 跳过这个空对象
         return;
      }
   }


   //用来判断是否需要继续依赖注入,false的时候就直接返回
   boolean continueWithPropertyPopulation = true;

    //hasInstantiationAwareBeanPostProcessors判断是否需要在注入属性值之前对这些参数值做最后一次的修改
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //具体通过调用postProcessAfterInstantiation方法,如果调用返回false,标识不必继续进行依赖注入。
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

    //如果不需要依赖注入 这里就直接返回
   if (!continueWithPropertyPopulation) {
      return;
   }

    //初始化一个默认的属性值
   PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    //如果配置文件显示的配置了依赖注入,就不会走以下的逻辑。
    //如果设置了相关的依赖配置方式,会遍历bean中的所有属性,根据类型和名称来完成相应注入,无需额外配置
   if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
        //对现有的属性值进行深度拷贝
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      // 根据名称注入
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }
      // 根据类型注入
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }
            //重新赋值属性值
      pvs = newPvs;
   }

    //这里检测了是否配置了后处理器。
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    //判断是否需要进行依赖检测
   boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

   PropertyDescriptor[] filteredPds = null;
    //配置了后处理器
   if (hasInstAwareBpps) {
        //如果没有属性值,就从配置文件中获取。
      if (pvs == null) {
         pvs = mbd.getPropertyValues();
      }
        //逐一的对每一个后处理器,进行处理
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //判断类型,校验是否是实例前后使用的处理器(后处理器分为实例化(BeanPostProcessor)、初始化(InstantiationAwareBeanPostProcessor)的两种)
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            //类型强制转换
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //进行后处理
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
               if (filteredPds == null) {
                    //筛选出所有需要进行依赖检测的属性编辑器
                  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
               }
                //对所有需要依赖检测的属性进行后处理
               pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvsToUse == null) {
                  return;
               }
            }

            //再次更新属性
            pvs = pvsToUse;
         }
      }
   }
   if (needsDepCheck) {
      if (filteredPds == null) {
           //筛选出所有需要进行依赖检测的属性编辑器
         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
        //依赖检测
      checkDependencies(beanName, mbd, filteredPds, pvs);
   }


   if (pvs != null) {
        //将属性注入到bean中
      applyPropertyValues(beanName, mbd, bw, pvs);
   }
}

        在populateBean函数中提供了属性注入的逻辑框架。

1.InstantiationAwareBeanPostProcessor处理器的PostProcessAfterInstantiation函数的应用。次函数可以控制程序是否继续进行属性填充。

2.根据注入类型(根据属性名或者根据属性类型),提起依赖的Bean,统一存入PropertyValues中。

3.应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理。

4.将所有PropertyValues中的属性填充到bean中。

上面最重要的3个方法分别是autowireByName、autowireByType和applyPropertyValues,接下来进一步逐一分析这几个功能的实现细节。

 

一、autowireByName

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

    //寻找bw中需要依赖注入的属性。
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      if (containsBean(propertyName)) {
            //递归初始化相关的Bean
         Object bean = getBean(propertyName);
                //存放依赖注入的属性值
         pvs.add(propertyName, 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");
         }
      }
   }
}

        理解这个方法的功能并不太困难,无非是在传入的参数bw中找出已经加载的bean,并递归实例化,进而加入到pvs中。

 

二、autowireByType

protected void autowireByType(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //获取类型转换器(用户自定义的)
   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
        //用户没有,我们就用spring自己的
      converter = bw;
   }

    //用于存放解析出来需要存放需要注入的属性
   Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //寻找bw中需要依赖注入的属性。
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      try {
            //获取对应属性名的属性描述器
         PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
         //所有object类型的属性都不进行注入
         if (Object.class != pd.getPropertyType()) {
            //搜索指定属性的set方法
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            // 检测属性的类型能否成功转成目标类型
            boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
            //创建需要被依赖注入的描述对象
            DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
            //根据容器的Bean定义解析出依赖关系,返回需要被注入的bean对象
            Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
            if (autowiredArgument != null) {
                //将属性和要进行注入的bean对象进行关联,保存到PropertyValues中
               pvs.add(propertyName, autowiredArgument);
            }
            
            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);
      }
   }
}

        对于根据类型自动注入的实现来说,寻找bw中需要依赖注入的属性也是第一步,让后遍历这些属性寻找类型匹配的bean,其中最为复杂的就是寻找出对应类型的bean,最为重要的也是这个功能,实现的逻辑被封装在DefaultListableBeanFactory类中的resolveDependency方法中。

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
     @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {


   descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    //对java8中的Optional类型进行处理
   if (Optional.class == descriptor.getDependencyType()) {
      return createOptionalDependency(descriptor, requestingBeanName);
   }
        //之前说过spring会提前曝光ObjectFactory,对此进行特殊处理
   else if (ObjectFactory.class == descriptor.getDependencyType() ||
         ObjectProvider.class == descriptor.getDependencyType()) {
      return new DependencyObjectProvider(descriptor, requestingBeanName);
   }
    //javax.inject.Provider也需要进行特殊处理
   else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
      return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
   }
   else {
        //对懒加载(@Lazy)进行处理,spring就不会立即创建注入属性,而是生成代理对象,来替代实例
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
      if (result == null) {
            //通用的处理逻辑
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}

接着上面的通用处理逻辑

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {


   InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
   try {
        //spring在第一次创建依赖的bean时,会保存这个bean的beanName作为shortcut
        //在第二次创建时,就可以直接根据beanName调用getBean方法,不需要在根据类型来重新查询一遍。
      Object shortcut = descriptor.resolveShortcut(this);
      if (shortcut != null) {
         return shortcut;
      }

        //注入属性的类型
      Class<?> type = descriptor.getDependencyType();
        //获取@Value中的value属性
      Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
      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()));
         }
      }

        //对数组、集合、容器类型进行处理。
        //确定集合类型->调用findAutowireCandidates方法,获取与组件类型匹配的map->符合beanNames就添加到autowiredBeanNames中。
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
         return multipleBeans;
      }

        //非集合类型的处理,直接通过findAutowireCandidates获取到对应类型的bean
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         return null;
      }


      String autowiredBeanName;
      Object instanceCandidate;

        //如果类型匹配的bean不止一个,spring进行筛选,失败就抛出异常
      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 {
         // 只有一个bean与其匹配,直接使用这个bean
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey();
         instanceCandidate = entry.getValue();
      }


      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }
      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
      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);
   }
}

        这个段逻辑虽然长,但是逻辑还是十分清晰,首先尝试对解析器进行解析,如果没有解析成功,那么可能是使用默认的解析器没有做任何处理,或者是使用了自定义的解析器,但是对于集合这类的类型并不在解析器的范围里,所以还需要再次对不同的类型进行不同情况的处理。

 

三、applyPropertyValues

        到了这里离成功就差最后一步,之前已经将所有需要依赖注入的属性和其对应注入的参数值存放到了PropertyValues中,但是还没有被应用到已经实例化的bean中。

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()) {
         try {
            //若该mpvs中的所有属性值都已经转换为对应的类型,则吧mpvs设置到beanWrapper中,
            bw.setPropertyValues(mpvs);
            return;
         }
         catch (BeansException ex) {
            throw new BeanCreationException(
                  mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();
   }
   else {
      original = Arrays.asList(pvs.getPropertyValues());
   }

    //获取用户的自定义类型转换器
   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
    //获取BeanDefinitionValueResolver,用于bean定义对象中包含的值解析为应用于目标bean实例的实际值
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);


   // 用于存放实际解析后的属性
   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();
            //解析后的值
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
         Object convertedValue = resolvedValue;
            //这个属性可以写并且不是一个嵌套在其他属性中的属性,也不是集合的索引属性。
         boolean convertible = bw.isWritableProperty(propertyName) &&
               !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
         if (convertible) {
            //用类型转换器进行转换
           convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         //将转换后的值存储起来,避免对每一个需要创建的bean都再次转换
         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标记成已经转换
      mpvs.setConverted();
   }


   // Set our (possibly massaged) deep copy.
   try {
        //构造MutablePropertyValues缓存到beanWrapper中
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值