@Autowire中byName和byType的实现过程

简介: @Autowire中byName和byType的实现过程

@Autowire的实现方式name与type

@Autowire装配本身有两种形式byName 与 byType,上一篇博文写了他们的用法以及使用的场景,现在来看看他们是怎么实现的,首先看populateBean方法,他是spring进行属性注入的方法,@Autowire本身就是属性注入的一部分

/**
* 属性注入
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
        } else {
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();

                while(var4.hasNext()) {
                    InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
                    if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }

            PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
            int resolvedAutowireMode = mbd.getResolvedAutowireMode();
            if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
                MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
              
                if (resolvedAutowireMode == 1) {
                    // 根据name自动注入
                    this.autowireByName(beanName, mbd, bw, newPvs);
                }

                if (resolvedAutowireMode == 2) {
                    // 根据Type自动注入
                    this.autowireByType(beanName, mbd, bw, newPvs);
                }

                pvs = newPvs;
            }

            boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = mbd.getDependencyCheck() != 0;
            PropertyDescriptor[] filteredPds = null;
            if (hasInstAwareBpps) {
                if (pvs == null) {
                    pvs = mbd.getPropertyValues();
                }

                PropertyValues pvsToUse;
                for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
                    InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
                    pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }

                        pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                }
            }

            if (needsDepCheck) {
                if (filteredPds == null) {
                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }

                this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
            }

            if (pvs != null) {
                // 将上面得到的依赖转化到已经实例化的bean中
                this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
            }

        }
    }
    
    

上面的代码是在scope为单例模式下,进行的属性注入源码,这段源码中有两个人方法,就是@Autowire中byName和byType的实现

    if (resolvedAutowireMode == 1) {
        // 根据name自动注入
        this.autowireByName(beanName, mbd, bw, newPvs);
    }

    if (resolvedAutowireMode == 2) {
        // 根据Type自动注入
        this.autowireByType(beanName, mbd, bw, newPvs);
    }


  1. autowireByName

       protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
              // 寻找BeanWrapper bw中需要依赖注入的属性
              String[] propertyNames = this.unsatisfiedNonSimpleProperties(mbd, bw);
              String[] var6 = propertyNames;
              int var7 = propertyNames.length;
    
              for(int var8 = 0; var8 < var7; ++var8) {
                  String propertyName = var6[var8];
                  if (this.containsBean(propertyName)) {
                      // 递归初始化相关的bean
                      Object bean = this.getBean(propertyName);
                      pvs.add(propertyName, bean);
                      // 注册依赖
                      this.registerDependentBean(propertyName, beanName);
                      if (this.logger.isTraceEnabled()) {
                          this.logger.trace("Added autowiring by name from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
                      }
                  } else if (this.logger.isTraceEnabled()) {
                      this.logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found");
                  }
              }
    
          }
    
  • 寻找BeanWrapper bw中需要依赖注入的属性
  • 循环遍历将这些属性放到MutablePropertyValues对象中,注意这里其实是传入了临时变量,并且改变了临时变量,在重构·代码的设计之道中要求尽量不要传入临时变量,但是在实际的工作中还是有很多场景要通过这种形式来实现,可见代码的设计是不拘一格的。
  1. autowireByType

       protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
              TypeConverter converter = this.getCustomTypeConverter();
              if (converter == null) {
                  converter = bw;
              }
    
              Set<String> autowiredBeanNames = new LinkedHashSet(4);
              // 寻找BeanWrapper bw中需要依赖注入的属性
              String[] propertyNames = this.unsatisfiedNonSimpleProperties(mbd, bw);
              String[] var8 = propertyNames;
              int var9 = propertyNames.length;
    
              for(int var10 = 0; var10 < var9; ++var10) {
                  String propertyName = var8[var10];
    
                  try {
                      PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                      if (Object.class != pd.getPropertyType()) {
                          MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                          boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                          DependencyDescriptor desc = new AbstractAutowireCapableBeanFactory.AutowireByTypeDependencyDescriptor(methodParam, eager);
                          Object autowiredArgument = this.resolveDependency(desc, beanName, autowiredBeanNames, (TypeConverter)converter);
                          if (autowiredArgument != null) {
                              pvs.add(propertyName, autowiredArgument);
                          }
    
                          Iterator var17 = autowiredBeanNames.iterator();
    
                          while(var17.hasNext()) {
                              // 注册依赖
                              this.registerDependentBean(autowiredBeanName, beanName);
                              if (this.logger.isTraceEnabled()) {
                                  this.logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'");
                              }
                          }
    
                          autowiredBeanNames.clear();
                      }
                  } catch (BeansException var19) {
                      throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, var19);
                  }
              }
    
          }
    

byType比byname相对复杂,因为byType要考虑到注入的对象是集合的情况,如

@Autowired
private List<Test> tests;

所以出现了autowiredBeanNames属性。

  1. 属性处理

上面的方法,无论是byName和byType其实都是对依赖属性的获取,并且把这些属性放到了MutablePropertyValues对象中,并没有应用到已经实例化的bean中这个bean在上面的方法中可以理解为BeanWrapper对象。
而转化是在this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs)方法

  protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (!pvs.isEmpty()) {
            if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
                ((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
            }

            MutablePropertyValues mpvs = null;
            List original;
            if (pvs instanceof MutablePropertyValues) {
                mpvs = (MutablePropertyValues)pvs;
                if (mpvs.isConverted()) {
                    try {
                        bw.setPropertyValues(mpvs);
                        return;
                    } catch (BeansException var18) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
                    }
                }

                original = mpvs.getPropertyValueList();
            } else {
                original = Arrays.asList(pvs.getPropertyValues());
            }

            TypeConverter converter = this.getCustomTypeConverter();
            if (converter == null) {
                converter = bw;
            }
            // 获取对应解析器
            BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
            List<PropertyValue> deepCopy = new ArrayList(original.size());
            boolean resolveNecessary = false;
            Iterator var11 = original.iterator();

            while(true) {
                while(var11.hasNext()) {
                    PropertyValue pv = (PropertyValue)var11.next();
                    if (pv.isConverted()) {
                        deepCopy.add(pv);
                    } else {
                        String propertyName = pv.getName();
                        Object originalValue = pv.getValue();
                        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);
                        Object convertedValue = resolvedValue;
                        boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                        if (convertible) {
                            convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
                        }

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

                try {
                    // 将MutablePropertyValues对象转换到BeanWrapper中
                    bw.setPropertyValues(new MutablePropertyValues(deepCopy));
                    return;
                } catch (BeansException var19) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
                }
            }
        }
    }


相关文章
|
24天前
|
Java 容器 Spring
Bean的实例化阶段
经过第一阶段,所有bean定义都通过BeanDefinition的方式注册到BeanDefinitionRegistry中当某个请求通过容器的getBean方法请求某个对象,或者因为依赖关系容器需要隐式的调用getBean时,就会触发第二阶段的活动:容器会首先检查所请求的对象之前是否已经实例化完成。 如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。 当该对象装配完毕后,容器会立即将其返回给请求方法使用。BeanFactory只是Spring IoC容器的一种实现,如果没有特殊指定,它采用采用延迟初始化策略:只有当访问容器中的某个对象时,才对
|
7月前
springBean注入循环解决
springBean注入循环解决
|
Java Spring
Spring中那些BeanPostProcessor在Bean实例化过程中的作用
Spring中那些BeanPostProcessor在Bean实例化过程中的作用
178 1
|
7月前
|
Java Spring 容器
Bean背后的魔法:揭秘Spring配置Bean的实现原理
Bean背后的魔法:揭秘Spring配置Bean的实现原理
64 0
Bean背后的魔法:揭秘Spring配置Bean的实现原理
|
Java Spring 容器
简单存 Bean 对象 -- 五大类注解以及 Bean 方法(下)
简单存 Bean 对象 -- 五大类注解以及 Bean 方法(下)
|
7月前
|
XML Java 数据格式
解释Spring中一个bean的注入过程
解释Spring中一个bean的注入过程
|
存储 Java Spring
简单存 Bean 对象 -- 五大类注解以及 Bean 方法(上)
简单存 Bean 对象 -- 五大类注解以及 Bean 方法(上)
|
XML Java 开发者
SpringBean的自动装配运行原理
SpringBean的自动装配运行原理
163 0
|
Java Spring
Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition
Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition
120 0
|
缓存 Java 容器
Spring源码学习:一篇搞懂@Autowire和@Resource注解的区别
最近在刷到很多文章讲解Spring IOC依赖注入时@Autowire和@Resource注解的区别,不同的文章总结出来的点有异同,所以还是看源码自己总结一下其两者的区别,及其用法。
156 0
Spring源码学习:一篇搞懂@Autowire和@Resource注解的区别