Spring源码(十一)-属性填充-populateBean

448 阅读29分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 5 天,点击查看活动详情

日积月累,水滴石穿 😄

前言

我们前面几篇已经将 bean的实例化、寻找 bean 注入点分析完了。可以知道如果不是通过构造方法进行属性赋值的话,那实例化的对象中的属性的值都是 null ,所以这篇我们来看看 Spring是如何给对象中的属性赋值的。

populateBean

方法位于 AbstractAutowireCapableBeanFactory类。

populateBean 方法传入三个参数:

  • beanName:bean名称
  • mdb:当前bean的定义
  • bw:当前实例的包装对象

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  // 没有实例化对象
  if(bw == null) {
    // 如果有为此bean定义属性值,则抛出异常
    if(mbd.hasPropertyValues()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
        "Cannot apply property values to null instance");
    } else {
      //直接返回,结束该方法
      return;
    }
  }
  // 可以提供InstantiationAwareBeanPostProcessor,控制对象的属性注入
  // 我们可以自己写一个InstantiationAwareBeanPostProcessor,然后重写 
  // postProcessAfterInstantiation方法返回false
  // 那么则不会进行属性填充了,直接返回
  //isSynthetic():bena 不是"合成"的,即未由应用程序本身定义
  // 是否持有 InstantiationAwareBeanPostProcessor
  if(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for(BeanPostProcessor bp: getBeanPostProcessors()) {
      if(bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (
          InstantiationAwareBeanPostProcessor) bp;
        // postProcessAfterInstantiation:实例化后,该方法默认返回true
        // 如果我们实现InstantiationAwareBeanPostProcessor,
        // 然后重写postProcessAfterInstantiation方法返回false
        // 将会阻止 Bean 的属性填充
        if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(),
            beanName)) {
          return;
        }
      }
    }
  }
  // 是否在BeanDefinition中设置了属性值
  // xml中 property 属性的解析
  PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() :
    null);
  //  autowire属性
  int resolvedAutowireMode = mbd.getResolvedAutowireMode();
  // 这里取的是xml中 autowire 属性配置的值 如果是byType(2)、byName(1),就会进入这段逻辑
  // 如果是使用 @Autowired,resolvedAutowireMode的值为 0
  if(resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode ==
    AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // byName
    if(resolvedAutowireMode == AUTOWIRE_BY_NAME) {
      autowireByName(beanName, mbd, bw, newPvs);
    }
    //byType
    if(resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
    // by_name是根据set方法名字找bean
    // by_type是根据所对应的set方法的参数类型找bean
    // 找到bean之后都要调用set方法进行注入
    // 注意,执行完这里的代码之后,这是把属性以及找到的值存在了pvs里面,并没有完成反射赋值
  }
  // 执行完了Spring的自动注入之后,就开始解析@Autowired、@Resource、@Value 等等注解
  // 是否有InstantiationAwareBeanPostProcessor
  boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  // 是否进行依赖检查,默认不进行依赖检查
  boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition
    .DEPENDENCY_CHECK_NONE);
  // @Autowired、@Value注解被AutowiredAnnotationBeanPostProcessor处理解析
  // @Resource 注解被CommonAnnotationBeanPostProcessor处理解析
  //这个两个类都是 InstantiationAwareBeanPostProcessor 接口的具体实现
  PropertyDescriptor[] filteredPds = null;
  if(hasInstAwareBpps) {
    if(pvs == null) {
      pvs = mbd.getPropertyValues();
    }
    for(BeanPostProcessor bp: getBeanPostProcessors()) {
      if(bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (
          InstantiationAwareBeanPostProcessor) bp;
        // 调用BeanPostProcessor分别解析@Autowired、@Resource、@Value 等等注解,得到属性值
        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) {
    // pvs存的就是属性已经对应的值
    applyPropertyValues(beanName, mbd, bw, pvs);
  }
}

我们先来看一下autowireByName方法,根据byName寻找 Bean。

autowireByName 装配

准备一个 B 类,类中提供 setOrder方法、setORder方法还有一个OrderService属性。

public class B {

	OrderService orderService;

	public void setOrder(OrderService order){
		System.out.println("setOrder = " +order);
	}
	public void setORder(OrderService order){
		System.out.println("setORder = " + order);
	}
}
public class OrderService {
}

//配置
<bean class="com.gongj.populateBean.OrderService" id="order"/>
 // 根据byName 注入属性
<bean class="com.gongj.populateBean.B" id="b" autowire="byName"/>
    
启动类 main 方法:
ClassPathXmlApplicationContext context =
	new ClassPathXmlApplicationContext("spring-config2.xml");

打印结果:setOrder = com.gongj.populateBean.OrderService@6bf2d08e

根据 byName自动注入,执行的是 setOrder方法,而不是 setORder方法。Spring 是如何去寻找的呢?跟着小杰一起来揭开这神秘的面纱吧!

autowireByName 源码解析

protected void autowireByName(String beanName, AbstractBeanDefinition mbd,
  BeanWrapper bw, MutablePropertyValues pvs) {
  // 获得当前实例作用域为 public 的 set方法名称(去掉set)
  //比如 setOrder -》 order
  //setORder -》 ORder
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  //循环得到的名称
  for(String propertyName: propertyNames) {
    //判断名称在单例池(singletonObjects)中是否存在  或者 在beanDefinitionMap中是否存在
    if(containsBean(propertyName)) {
      // 根据名称直接去找bean,这就是byName
      Object bean = getBean(propertyName);
      // 将属性名称、属性值添加到pvs中
      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");
      }
    }
  }
}

image-20210324203952784.png 可以看到 setOrder方法被去掉了 set 之后变为了 orderO由大写变为了小写 o;而setORder方法被去掉了 set 之后变为了ORder,原样返回了。

处理流程

autowireByName 的处理流程:

1、获得所有公开的 set 方法(也会获取到父类的)。如果 set 方法的名称是 setOrder,返回的就是order,如果 set 方法的名称是 setORder,返回就是ORder

2、循环获得的名称,先判断在容器中是否已经存在,存在就调用 getBean 方法,可以进行创建也可能直接获取。

3、将获得的对象赋值给 pvs,key 为 获得的名称,value为找到的对象。

4、注册依赖

下面就分别简单的分析一下各个流程:

1、unsatisfiedNonSimpleProperties

获得当前实例所有公开的(包括父类) set 方法,有如下几种情况:

1、无返回值的set有参方法(只能是一个参数),示例:
    public void setOrderService(OrderService order){}
2、无参有返回值的get方法(返回类型不能是void),示例:
    public String getba(){ return null;}
3、返回值为boolean类型的is无参方法,示例:
    public boolean isDel(){return false;}

OK,继续往下看。。。

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd,
  BeanWrapper bw) {
  Set <String> result = new TreeSet < > ();
  // 获得在BeanDefinition中添加的属性值
  PropertyValues pvs = mbd.getPropertyValues();
  // 获得当前实例的所有公开的(包括父类) get、set 方法
  // 一个方法就是一个 PropertyDescriptor 对象
  // PropertyDescriptor 这个类已经不是 Spring 的类,它属于java.beans包下
  PropertyDescriptor[] pds = bw.getPropertyDescriptors();
  // 对找到的属性进行过滤,确定哪些属性是需要进行自动装配的
  for(PropertyDescriptor pd: pds) {
    // 属性有set方法,getWriteMethod就不会为 null 
    // 并且没有通过DependencyCheck排除
    // 并且没有在BeanDefinition中给该属性赋值
    // 并且属性的类型不是简单类型
    if(pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !
      pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())
    ) {
      result.add(pd.getName());
    }
  }
  // 将集合转换为数组
  // 返回过滤之后的结果,后续只对这些属性进行自动装配
  return StringUtils.toStringArray(result);
}

getPropertyDescriptors方法所返回的 PropertyDescriptorjava 的对象。这已经不是 Spring 的了。

这里也简单的贴一下吧!如果一直DEBUG会进入到 Introspector类的 getBeanInfo方法。这个类是java的类。

public static BeanInfo getBeanInfo(Class<?> beanClass)
        throws IntrospectionException
    {
  if (!ReflectUtil.isPackageAccessible(beanClass)) {
    return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
  }
  ThreadGroupContext context = ThreadGroupContext.getContext();
  BeanInfo beanInfo;
  synchronized (declaredMethodCache) {
    beanInfo = context.getBeanInfo(beanClass);
  }
  if (beanInfo == null) {
    // 看这里  new Introspector(beanClass, null, USE_ALL_BEANINFO) 这个构造方法里就有获取父类的逻辑,构造方法执行完毕之后,调用 getBeanInfo 方法
    beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
    synchronized (declaredMethodCache) {
      context.putBeanInfo(beanClass, beanInfo);
    }
  }
  return beanInfo;
}

getBeanInfo

private BeanInfo getBeanInfo() throws IntrospectionException {
  BeanDescriptor bd = getTargetBeanDescriptor();
  MethodDescriptor mds[] = getTargetMethodInfo();
  EventSetDescriptor esds[] = getTargetEventInfo();
  //这里我们只看这个方法,很熟悉了吧
  PropertyDescriptor pds[] = getTargetPropertyInfo();
  int defaultEvent = getTargetDefaultEventIndex();
  int defaultProperty = getTargetDefaultPropertyIndex();
  return new GenericBeanInfo(bd, esds, defaultEvent, pds,
                          defaultProperty, mds, explicitBeanInfo);
}  
getTargetPropertyInfo
private PropertyDescriptor[] getTargetPropertyInfo() {
  PropertyDescriptor[] explicitProperties = null;
  if(explicitBeanInfo != null) {
    explicitProperties = getPropertyDescriptors(this.explicitBeanInfo);
  }
  if(explicitProperties == null && superBeanInfo != null) {
    // We have no explicit BeanInfo properties.  Check with our parent.
    addPropertyDescriptors(getPropertyDescriptors(this.superBeanInfo));
  }
  for(int i = 0; i < additionalBeanInfo.length; i++) {
    addPropertyDescriptors(additionalBeanInfo[i].getPropertyDescriptors());
  }
  if(explicitProperties != null) {
    // Add the explicit BeanInfo data to our results.
    addPropertyDescriptors(explicitProperties);
  } else {
    // 看这里
    // 获得当前类所有公开的方法
    Method methodList[] = getPublicDeclaredMethods(beanClass);
    for(int i = 0; i < methodList.length; i++) {
      Method method = methodList[i];
      if(method == null) {
        continue;
      }
      //如果当前方法是 static 的,则跳过
      int mods = method.getModifiers();
      if(Modifier.isStatic(mods)) {
        continue;
      }
      // 方法名称
      String name = method.getName();
      // 方法的参数类型
      Class <? > [] argTypes = method.getParameterTypes();
      // 方法的返回类型
      Class <? > resultType = method.getReturnType();
      // 方法的参数个数
      int argCount = argTypes.length;
      PropertyDescriptor pd = null;
      // 如果方法名称的长度小于等于3,也就是说你的方法名称叫 set() get()
      // 并且你的方法名不是以 is 开头的 则跳过当前方法
      if(name.length() <= 3 && !name.startsWith(IS_PREFIX)) {
        // Optimization. Don't bother with invalid propertyNames.
        continue;
      }
      try {
        // 如果参数个数为 0 ,也就是无参
        if(argCount == 0) {
          // 方法名称以 get 开头
          if(name.startsWith(GET_PREFIX)) {
            // 构建一个 PropertyDescriptor 对象 
            // name.substring(3) 这里截取了 get 这个三个字
            pd = new PropertyDescriptor(this.beanClass, name.substring(3),
              method, null);
          }
          // 如果返回类型是 boolean 并且 方法名称以 is 开头
          else if(resultType == boolean.class && name.startsWith(IS_PREFIX)) {
            // 构建一个 PropertyDescriptor 对象 
            // name.substring(2) 这里截取了 is 这个两个字
            pd = new PropertyDescriptor(this.beanClass, name.substring(2),
              method, null);
          }
        }
        // 如果参数个数为1
        else if(argCount == 1) {
          if(int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
            // 不管,这是 PropertyDescriptor 的子类
            pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(
              3), null, null, method, null);
          }
          // 如果返回类型是 void 并且 方法名称以 set 开头
          else if(void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
            // 构建一个 PropertyDescriptor 对象 
            // name.substring(3) 这里截取了 set 这个三个字
            pd = new PropertyDescriptor(this.beanClass, name.substring(3),
              null, method);
            if(throwsException(method, PropertyVetoException.class)) {
              pd.setConstrained(true);
            }
          }
        }
        // 如果参数个数为2
        else if(argCount == 2) {
          if(void.class.equals(resultType) && int.class.equals(argTypes[0]) &&
            name.startsWith(SET_PREFIX)) {
            pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(
              3), null, null, null, method);
            if(throwsException(method, PropertyVetoException.class)) {
              pd.setConstrained(true);
            }
          }
        }
      } catch(IntrospectionException ex) {
        pd = null;
      }
      if(pd != null) {
        if(propertyChangeSource) {
          pd.setBound(true);
        }
        addPropertyDescriptor(pd);
      }
    }
  }
  processPropertyDescriptors();
  PropertyDescriptor result[] = properties.values().toArray(new PropertyDescriptor[
    properties.size()]);
  if(defaultPropertyName != null) {
    for(int i = 0; i < result.length; i++) {
      if(defaultPropertyName.equals(result[i].getName())) {
        defaultPropertyIndex = i;
      }
    }
  }
  return result;
}

看完上面这个方法,可以知道 PropertyDescriptor存的可以是 get 方法,也可以是 set 方法。然后再看一个方法:PropertyDescriptor 的构造方法。

PropertyDescriptor
PropertyDescriptor(Class <?> bean, String base, Method read, Method write) throws IntrospectionException {
  if(bean == null) {
    throw new IntrospectionException("Target Bean class is null");
  }
  setClass0(bean);
  // 将名称再次进行转换 比如我们所熟知的:类名首字母小写
  setName(Introspector.decapitalize(base));
  // read 就是get方法
  setReadMethod(read);
  // write 就是 set 方法 (重点:会根据这个属性是否为空判断是否有set方法)
  setWriteMethod(write);
  // 去掉get或者set的名称 示例:setOrder,base = Order
  this.baseName = base;
}
decapitalize
public static String decapitalize(String name) {
    if (name == null || name.length() == 0) {
        return name;
    }
    // 如果名称长度大于 1 并且 第二个字母是大写的 并且 第一个字母是大写的
    // 则原样返回
    // 示例:ORder -》 ORder
    if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
        Character.isUpperCase(name.charAt(0))){
        return name;
    }
    char chars[] = name.toCharArray();
    // 将第一个字母转换为小写
    // 示例:Order -》 order
    chars[0] = Character.toLowerCase(chars[0]);
    return new String(chars);
}

实例

准备一个 A 类,并准备其他配置。

public class A {
  //无参set方法
  public void seta() {}
    //无参set方法
  public boolean isBoolean() {
      return false;
    }
    //有参set方法
  public void seta2(ProductService productService) {}
  public void seta3(OrderService orderService, OrderService orderService2) {}
    //无参无返回get方法
  public void getb() {}
    //无参有返回get方法
  public String getbb() {
      return "fefe";
    }
    //有参无返回get方法
  public void getb2(OrderService orderService) {}
  public void getb3(OrderService orderService, ProductService productService) {}
    //有参有返回get方法
  public String getb4(OrderService orderService) {
    return "DDF";
  }
  public String getb5(OrderService orderService, ProductService productService) {
    return "DDefeF";
  }
}

//其他类
@Component
public class OrderService {}

@Service
public class ProductService {} 

配置

<bean class="com.gongj.populateBean.A" id="a" autowire="byName"></bean>
<!--扫描包路径-->
<context:component-scan base-package="com.gongj.populateBean"/>

启动启动类,getPropertyDescriptors()方法响应如下:

image-20210829132001495.png

a2也就是 seta2()bb也就是getbb()booleanisBoolean()class是属于父类ObjectgetClass()

2、containsBean

@Override
public boolean containsBean(String name) {
  String beanName = transformedBeanName(name);
  // 单例池(singletonObjects)中是否存在  或者 beanDefinitionMap中是否存在
  if(containsSingleton(beanName) || containsBeanDefinition(beanName)) {
    // 如果存在 先判断它是不是以 & 开头,如果是,则判断它是不是 FactoryBean
    return(!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
  }
  // Not found -> check parent.
  // 获得父BeanFactory
  BeanFactory parentBeanFactory = getParentBeanFactory();
  // 看父级中是否存在
  return(parentBeanFactory != null && parentBeanFactory.containsBean(
    originalBeanName(name)));
}

3、registerDependentBean

这个方法中的参数名各位可能会弄混淆,这里提一下。

registerDependentBean(String beanName, String dependentBeanName)

在调用方法的时候,它将找到的set方法的名称作为第一个参数,当前的bean名称作为第二个参数。

也就是上面举得例子,B类中有OrderServie属性,说明 B 依赖 OrderServie。所以 beanName = ORder或者为orderdependentBeanName = b

public void registerDependentBean(String beanName, String dependentBeanName) {
  //确定原始名称,根据 beanName 去 aliasMap 中寻找,获得真正的 beanName
  String canonicalName = canonicalName(beanName);
  // computeIfAbsent:如果 key 对应的 value 不存在,
  // 则使用获取 remappingFunction 重新计算后的值,
  // 并保存为该 key 的 newValue,否则返回 value
  // dependentBeanMap:我被谁依赖  order 被 b 依赖  key为 order,value 为 b 
  synchronized(this.dependentBeanMap) {
      Set < String > dependentBeans = this.dependentBeanMap.computeIfAbsent(
        canonicalName, k - > new LinkedHashSet < > (8));
      // 如果添加失败则返回,添加失败也就代表已经存在了
      if(!dependentBeans.add(dependentBeanName)) {
        return;
      }
    }
    // dependenciesForBeanMap:我依赖谁  b 依赖 order,key为b,value 为 order
  synchronized(this.dependenciesForBeanMap) {
    Set < String > dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(
      dependentBeanName, k - > new LinkedHashSet < > (8));
    dependenciesForBean.add(canonicalName);
  }
}

autowireByType 装配

将上面的 byName 修改为 byType

<bean class="com.gongj.populateBean.B" id="b" autowire="byType"/>

结果:
setORder = com.gongj.populateBean.OrderService@ea30797
setOrder = com.gongj.populateBean.OrderService@ea30797

autowireByType 源码解析

protected void autowireByType(String beanName, AbstractBeanDefinition mbd,
  BeanWrapper bw, MutablePropertyValues pvs) {
  // 获得类型转换器
  TypeConverter converter = getCustomTypeConverter();
  if(converter == null) {
    converter = bw;
  }
  Set < String > autowiredBeanNames = new LinkedHashSet < > (4);
  // 获得当前实例作用域为 public 的 set方法名称(去掉set)
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  for(String propertyName: propertyNames) {
    try {
      // 获得属性描述对象
      PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
      // 当前set方法的参数属性的类型不是Object类
      if(Object.class != pd.getPropertyType()) {
        // methodParam:方法参数,包含set方法和set方法中的参数信息
        MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
        // 当前Bean是否实现了PriorityOrdered,没有实现:true 实现:false
        boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
        //DependencyDescriptor:方法已经见名知意了哈 依赖描述
        //示例:public void setOrderService(OrderService order){}
        //就是 OrderService 的描述信息
        // 这里指定了 DependencyDescriptor 的子类为 AutowireByTypeDependencyDescriptor
        DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(
          methodParam, eager);
        // 根据 desc 找bean
        Object autowiredArgument = resolveDependency(desc, beanName,
          autowiredBeanNames, converter);
        if(autowiredArgument != null) {
          // 将属性名称、属性值添加到pvs中
          pvs.add(propertyName, autowiredArgument);
        }
        for(String autowiredBeanName: autowiredBeanNames) {
          //注册依赖Bean
          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);
    }
  }
}

这里先提一句,为什么要给 DependencyDescriptor指定子类 AutowireByTypeDependencyDescriptor呢?

private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {
  public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter,
    boolean eager) {
    super(methodParameter, false, eager);
  }
  @Override
  public String getDependencyName() {
    return null;
  }
}

可以看到 AutowireByTypeDependencyDescriptor是一个静态的内部类,里面就一个构造方法和一个getDependencyName方法,而且 getDependencyName方法返回 null。依赖的名称直接返回null,就是如果你根据类型找到多个了,你都没办法根据名称再去寻找了。这很byType。为什么需要如此控制呢?主要是由于resolveDependency是公用方法,所以就只能从入参控制了。resolveDependency 方法我们等下再讲。我们先来看下如果 autowire属性的值不为 byName 或者 byType 的情况。


@Autowired装配

@Autowired装配也就是不属于 byName、byType两种装配方式的其他方式,首先先将上述代码修改一下,去掉autowire="byType"

  • xml修改
<bean class="com.gongj.populateBean.OrderService" id="order"/>
<!--autowire="byType" 去掉-->
<bean class="com.gongj.populateBean.B" id="b"/>
<!--扫描包路径-->
<context:component-scan base-package="com.gongj.populateBean"/>
  • B 类中增加一个 test方法,并在 orderService属性上增加 @Autowired注解
public class B {

	@Autowired
	OrderService orderService;

	public void test(){
		System.out.println("orderService = " + orderService);
	}
	public void setOrder(OrderService order){
		System.out.println("setOrder = " +order);
	}
	public void setORder(OrderService order){
		System.out.println("setORder = " + order);
	}
}
  • 启动类增加调用方法
public static void main(String[] args) {
    ClassPathXmlApplicationContext context =
        new ClassPathXmlApplicationContext("spring-config2.xml");
    B bean = context.getBean(B.class);
    bean.test();
}
结果:
orderService = com.gongj.populateBean.OrderService@5a39699c   

从结果可以看出来,这时并没有再执行那两个 set 方法。

源码解析

// ==== 执行完了Spring的byName、byType自动注入之后,就开始解析@Autowired、@Resource等等注解 ==== 

//是否有InstantiationAwareBeanPostProcessor
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()) {
    if(bp instanceof InstantiationAwareBeanPostProcessor) {
      InstantiationAwareBeanPostProcessor ibp = (
        InstantiationAwareBeanPostProcessor) bp;
      // 调用BeanPostProcessor分别解析@Autowired、@Resource、@Value等等,得到属性值
      // @Autowired、@Value注解被AutowiredAnnotationBeanPostProcessor处理解析
      // @Resource注解被CommonAnnotationBeanPostProcessor处理解析
      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;
    }
  }
}

上述代码还是比较容易理解的,首先先判断是否有InstantiationAwareBeanPostProcessor这个BeanPostProcessor,有这个BeanPostProcessor才会去执行 postProcessProperties方法。

进入到 ``InstantiationAwareBeanPostProcessorpostProcessProperties`方法,该方法是没有具体实现逻辑的,具体实现在子类中。

@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    throws BeansException {

    return null;
}

本篇只介绍AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,先来看下其中一个子类AutowiredAnnotationBeanPostProcessor

image-20210401213241491.png

1、AutowiredAnnotationBeanPostProcessor

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean,
  String beanName) {
  // InjectionMetadata中保存了所有被@Autowired,@Value,@Inject注解标注的属性、方法
  // 在这里已经被解析过了 AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName),这里也就从缓存中拿一下(忘记了可以再看看上一篇)
  InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(),
    pvs);
  try {
    //调用 inject
    metadata.inject(bean, beanName, pvs);
  }
  catch(BeanCreationException ex) {
    throw ex;
  }
  catch(Throwable ex) {
    throw new BeanCreationException(beanName,
      "Injection of autowired dependencies failed", ex);
  }
  return pvs;
}

进入到 inject方法

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  Collection < InjectedElement > checkedElements = this.checkedElements;
  Collection < InjectedElement > elementsToIterate = (checkedElements != null ?
    checkedElements : this.injectedElements);
  if(!elementsToIterate.isEmpty()) {
    // 遍历每个注入点,进行注入,注入点可以是属性、方法
    for(InjectedElement element: elementsToIterate) {
      if(logger.isTraceEnabled()) {
        logger.trace("Processing injected element of bean '" + beanName +
          "': " + element);
      }
      // element可能是Method,也可能是Field
      element.inject(target, beanName, pvs);
    }
  }
}

然后调试进入element.inject

protected void inject(Object target, @Nullable String requestingBeanName, @
  Nullable PropertyValues pvs)
throws Throwable {
  // 如果是属性,则反射赋值
  if(this.isField) {
    Field field = (Field) this.member;
    ReflectionUtils.makeAccessible(field);
    field.set(target, getResourceToInject(target, requestingBeanName));
  }
  else {
    // 检查当前的属性是不是通过by_name和by_type来注入的
    if(checkPropertySkipping(pvs)) {
      return;
    }
    try {
      // 如果是方法,则通过方法赋值
      // 这里的方法并不是一定要setXX方法
      Method method = (Method) this.member;
      ReflectionUtils.makeAccessible(method);
      method.invoke(target, getResourceToInject(target, requestingBeanName));
    }
    catch(InvocationTargetException ex) {
      throw ex.getTargetException();
    }
  }
}

在解析AutowiredAnnotationBeanPostProcessor时,这个方法不会被执行,该方法有两个子类。直接上图。

各位还记得缓存里面存的值吧!分别是:

currElements.add(new AutowiredFieldElement(field,required));

currElements.add(new AutowiredMethodElement(method, required, pd)); image-20210401221006633.png 两个私有的内部类,一个是 AutowiredFieldElement,用来解析字段。还有一个是 AutowiredMethodElement,用来解析方法。

AutowiredFieldElement.inject

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  Field field = (Field) this.member;
  Object value;
  if(this.cached) {
    // 当前注入点已经注入过了,有缓存了,则利用cachedFieldValue去找对应的bean
    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
  } else {
    //  Spring在真正查找属性对应的对象之前, 会先将该属性的描述封装成一个DependencyDescriptor对象,
    //  里面保存了Filed、是否强制需要即required为true, 以及属性所在的类(即Field所在的类Class对象)
    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    desc.setContainingClass(bean.getClass());
    Set < String > autowiredBeanNames = new LinkedHashSet < > (1);
    Assert.state(beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = beanFactory.getTypeConverter();
    try {
      // 根据field去寻找合适的bean,调用 resolveDependency
      // 这里也是调用 resolveDependency 方法,与在进行 byType 调用同一个方法。但是方法入参不一样
	  // 这里传入的类型是 DependencyDescriptor
        value = beanFactory.resolveDependency(desc, beanName,
        autowiredBeanNames, typeConverter);
    } catch(BeansException ex) {
      throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(
        field), ex);
    }
    synchronized(this) {
      // 进行缓存
      if(!this.cached) {
        if(value != null || this.required) {
          this.cachedFieldValue = desc;
          // 注册依赖
          registerDependentBeans(beanName, autowiredBeanNames);
          if(autowiredBeanNames.size() == 1) {
            String autowiredBeanName = autowiredBeanNames.iterator().next();
            // beanFactory中存在该 autowiredBeanName 并且 该autowiredBeanName的Bean的类型与字段的类型匹配,对解析得到的对象进行缓存
            if(beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(
                autowiredBeanName, field.getType())) {
              // ShortcutDependencyDescriptor 在后面会被使用到,这里是一个缓存
              this.cachedFieldValue = new ShortcutDependencyDescriptor(desc,
                autowiredBeanName, field.getType());
            }
          }
        } else {
          this.cachedFieldValue = null;
        }
        this.cached = true;
      }
    }
  }
  // 反射设值
  if(value != null) {
    ReflectionUtils.makeAccessible(field);
    field.set(bean, value);
  }
}
}

构建一个DependencyDescriptor 对象,然后调用 resolveDependency方法。如果解析完之后的值不为null,则进行反射设值。

AutowiredMethodElement.inject

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  if(checkPropertySkipping(pvs)) {
    return;
  }
  Method method = (Method) this.member;
  Object[] arguments;
  if(this.cached) {
    // 解析缓存好的参数
    arguments = resolveCachedArguments(beanName);
  } else {
    // 参数个数
    int argumentCount = method.getParameterCount();
    arguments = new Object[argumentCount];
    // 构建 DependencyDescriptor 对象(注:这里是一个数组)
    DependencyDescriptor[] descriptors = new DependencyDescriptor[
      argumentCount];
    // 记录自动注入的beanName,多少个参数就有多少个自动注入的beanName
    Set < String > autowiredBeans = new LinkedHashSet < > (argumentCount);
    Assert.state(beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = beanFactory.getTypeConverter();
    // 循环当前方法中的每个参数
    // 这里就解决了在xml中配置byType时,自动装配的方法参数只能为一个
    for(int i = 0; i < arguments.length; i++) {
      // 方法参数对象
      MethodParameter methodParam = new MethodParameter(method, i);
      // 将该属性的描述封装成一个DependencyDescriptor对象
      // 里面保存了方法参数对象、是否强制需要即required为true, 以及方法所在的类
      // 一个方法参数就是一个 DependencyDescriptor 对象
      DependencyDescriptor currDesc = new DependencyDescriptor(methodParam,
        this.required);
      currDesc.setContainingClass(bean.getClass());
      descriptors[i] = currDesc;
      try {
        // 调用 resolveDependency 方法
        Object arg = beanFactory.resolveDependency(currDesc, beanName,
          autowiredBeans, typeConverter);
        if(arg == null && !this.required) {
          arguments = null;
          break;
        }
        arguments[i] = arg;
      } catch(BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(
          methodParam), ex);
      }
    }
    // 循环结束======
    // arguments中存储的就是所找到的bean对象,构造为ShortcutDependencyDescriptor对象进行缓存
    // descriptors中存储的就是以方法参数构建的DependencyDescriptor对象
    synchronized(this) {
      // 进行缓存
      if(!this.cached) {
        if(arguments != null) {
          DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(
            descriptors, arguments.length);
          // 注册依赖
          registerDependentBeans(beanName, autowiredBeans);
          // 注入Bean的个数与参数个数一致
          if(autowiredBeans.size() == argumentCount) {
            Iterator < String > it = autowiredBeans.iterator();
            // 方法的参数类型
            Class <? > [] paramTypes = method.getParameterTypes();
            for(int i = 0; i < paramTypes.length; i++) {
              String autowiredBeanName = it.next();
              // beanFactory中存在该 autowiredBeanName 并且
              // 该autowiredBeanName的Bean的类型与字段的类型匹配,对解析得到的对象进行缓存
              if(beanFactory.containsBean(autowiredBeanName) && beanFactory
                .isTypeMatch(autowiredBeanName, paramTypes[i])) {
                // ShortcutDependencyDescriptor 在后面会被使用到,这里是一个缓存
                cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
                  descriptors[i], autowiredBeanName, paramTypes[i]);
              }
            }
          }
          this.cachedMethodArguments = cachedMethodArguments;
        } else {
          this.cachedMethodArguments = null;
        }
        this.cached = true;
      }
    }
  }
  // 反射设值
  if(arguments != null) {
    try {
      ReflectionUtils.makeAccessible(method);
      method.invoke(bean, arguments);
    } catch(InvocationTargetException ex) {
      throw ex.getTargetException();
    }
  }
}

获取方法中的每个参数构建一个DependencyDescriptor 对象,然后调用 resolveDependency方法。最终如果解析完之后的值不为null,则进行反射设值。

resolveDependency

我们最终来到了AutowireCapableBeanFactory.resolveDependency 方法,这个方法有几个参数:

Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter);
  • descriptor:依赖描述,可以是field(属性字段)、methodI(普通方法参数)、constructor(构造方法参数)
  • requestingBeanName:当前正在进行依赖注入的 beanName,比如 b。
  • autowiredBeanNames:记录注入给当前依赖的 beanName,比如 orderService。
  • typeConverter:类型转换器

具体实现在 DefaultListableBeanFactorresolveDependency中。

@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @
  Nullable Set < String > autowiredBeanNames, @Nullable TypeConverter typeConverter
) throws BeansException {
  // DependencyDescriptor表示一个依赖,可以是一个属性字段,可能是一个构造方法参数,可能是普通方法参数
  // 初始化ParameterNameDiscoverer,用于解析方法参数名称
  descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
  // 如果依赖的类型是Optional
  // 可以这么写 :Optional<OrderService> orderService;
  // 获得具体类型:orderService.get()
  if(Optional.class == descriptor.getDependencyType()) {
    return createOptionalDependency(descriptor, requestingBeanName);
  }
  // 如果依赖的类型是ObjectFactory 或者是 ObjectProvider
  // 可以这么写:ObjectFactory<OrderService> orderService;
  // 获得具体类型: orderService.getObject()
  // 这种写法解决了一个问题,具体前往博文:
  else if(ObjectFactory.class == descriptor.getDependencyType() ||
    ObjectProvider.class == descriptor.getDependencyType()) {
    return new DependencyObjectProvider(descriptor, requestingBeanName);
  }
  // 如果依赖的类型是javaxInjectProviderClass
  else if(javaxInjectProviderClass == descriptor.getDependencyType()) {
    return new Jsr330Factory().createDependencyProvider(descriptor,
      requestingBeanName);
  } else {
    // 通用处理逻辑
    // 在使用@Autowired注解时,也可以使用@Lazy注解,到时候注入的会是一个代理对象
    // 有 @Lazy 注解,result 才会有值
    Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
      descriptor, requestingBeanName);
    if(result == null) {
      // 通过解析descriptor找到bean对象
      result = doResolveDependency(descriptor, requestingBeanName,
        autowiredBeanNames, typeConverter);
    }
    return result;
  }
}

这里我们关注通用处理逻辑:doResolveDependency(),其实不论是Optional方式或者ObjectFactory方式,都会调用到doResolveDependency()方法。

doResolveDependency

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @
  Nullable Set < String > autowiredBeanNames, @Nullable TypeConverter typeConverter
) throws BeansException {
  InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(
    descriptor);
  try {
    // 如果DependencyDescriptor是一个ShortcutDependencyDescriptor,
    // 那么会直接根据beanName从beanFactory中获取bean,
    // 在利用@Autowired注解来进行依赖注入时会利用ShortcutDependencyDescriptor来进行依赖注入的缓存,
    // 表示当解析完某个依赖信息后,会把依赖的bean的beanName缓存起来
    // 忘记了的话,可以看看之前的逻辑:
    // AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement
    // AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
    Object shortcut = descriptor.resolveShortcut(this);
    if(shortcut != null) {
      return shortcut;
    }
    // 获取descriptor具体的类型,可能是Filed、普通方法参数、构造方法参数
    Class <? > type = descriptor.getDependencyType();
    // 获取@Value注解中所配置的值
    // 可以这么写:
    //@Autowired
    //@Value("xxx")
    //OrderService orderService;
    // 在@Autowired标注的字段或者方法上可以再加上@Value,所以如果有@Value,则需要先解析@Value的值
    // 如果有值,并且类型转换成功,则直接返回
    // getSuggestedValue方法具体在 QualifierAnnotationAutowireCandidateResolver 中被实现
    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);
        // 解析Spring EL表达式,解析"#"符号(可以进行运算,可以写某个bean的名字)
        // 解析不了,原样返回
        value = evaluateBeanDefinitionString(strVal, bd);
      }
      TypeConverter converter = (typeConverter != null ? typeConverter :
        getTypeConverter());
      try {
        // 进行类型转换
        return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
      }
      return(descriptor.getField() != null ? converter.convertIfNecessary(
        value, type, descriptor.getField()) : converter.convertIfNecessary(
        value, type, descriptor.getMethodParameter()));
    }
  }
  // 没有使用@Value注解 ===========
  // 要注入的依赖的类型是不是一个Map、Array、Collection
  // 注入的属性可以这样写:
  // 1、List<OrderService> orderService;
  // 2、Map<String,OrderService> maps;
  // 3、OrderService[] a;
  // resolveMultipleBeans 方法也就是了调用了下面的 findAutowireCandidates 方法
  // 然后拿到 findAutowireCandidates 方法的返回值,进行了类型转换
  // 这里就不在单独拎出来讲了,各位DEGUG一遍就了解了
  Object multipleBeans = resolveMultipleBeans(descriptor, beanName,
    autowiredBeanNames, typeConverter);
  if(multipleBeans != null) {
    return multipleBeans;
  }
  // 首先通过type找,可能找到多个
  // 返回值为Map:key = 成功匹配的beanName,value = 可能是具体的实例对象,也有可能暂时只是Class对象
  Map < String, Object > matchingBeans = findAutowireCandidates(beanName,
    type, descriptor);
  if(matchingBeans.isEmpty()) {
    // 如果没有找到想要的 bean,则判断当前需要注入的依赖是否是必须的,即 required = true
    if(isRequired(descriptor)) {
      raiseNoMatchingBeanFound(type, descriptor.getResolvableType(),
        descriptor);
    }
    // 不是必须,返回 null
    return null;
  }
  // 依赖的beanName
  String autowiredBeanName;
  // 确认好的对象
  Object instanceCandidate;
  // 根据type找到了多个
  if(matchingBeans.size() > 1) {
    // 找到多个,去尝试确定出唯一的一个
    //有几种筛选方式:
    //1、@Primary
    //2、@Priority
    //3、byName,也就属性名称,或者是方法参数名称
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if(autowiredBeanName == null) {
      // 还是没有确认唯一需要的bean
      if(isRequired(descriptor) || !indicatesMultipleBeans(type)) {
        // 当前依赖是required,或者不是数组或Collection或Map ,抛异常
        return descriptor.resolveNotUnique(descriptor.getResolvableType(),
          matchingBeans);
      } else {
        return null;
      }
    }
    //确认了唯一一个,根据 autowiredBeanName ,也就是 beanName获得 候选实例
    instanceCandidate = matchingBeans.get(autowiredBeanName);
  }
  // 就找到了一个
  else {
    Map.Entry < String, Object > entry = matchingBeans.entrySet().iterator().next();
    autowiredBeanName = entry.getKey();
    instanceCandidate = entry.getValue();
  }
  if(autowiredBeanNames != null) {
    // 将注入的 beanName 缓存起来
    autowiredBeanNames.add(autowiredBeanName);
  }
  //如果候选实例还是 Class 对象
  if(instanceCandidate instanceof Class) {
    // 调用beanFactory.getBean(beanName); 创建bean对象
    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);
}
}

上面的流程比较复杂,直接上图,大致流程如下: 1603095595006-374adc82-c3ef-43ad-baf6-68612a874925.png 流程图来源于图灵学院。看完流程图,对整个流程的理解应该会有很大的帮助!我们继续看源码。

findAutowireCandidates

该方法位于DefaultListableBeanFactory类,作用是寻找自动装配的候选者。

protected Map < String, Object > findAutowireCandidates(@Nullable String beanName,
  Class <? > requiredType, DependencyDescriptor descriptor) {
  // 根据requiredType找到candidateNames,表示根据type找到了候选beanNames
  // Ancestors是祖先的意思,所以这个方法是去当前beanfactory以及父级beanfactory中
  // 去找类型为requiredType的bean的名字
  String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    this, requiredType, true, descriptor.isEager());
  Map < String, Object > result = new LinkedHashMap < > (candidateNames.length);
  // 先从resolvableDependencies中进行匹配
  for(Map.Entry < Class <? > , Object > classObjectEntry: this.resolvableDependencies
    .entrySet()) {
    Class <? > autowiringType = classObjectEntry.getKey();
    // requiredType类是不是继承或实现了autowiringType, autowiringType为父类或接口,子类对象可以赋值给父类属性
    if(autowiringType.isAssignableFrom(requiredType)) {
      //  是resolvableDependencies中的子类所存的对象
      Object autowiringValue = classObjectEntry.getValue();
      autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue,
        requiredType);
      if(requiredType.isInstance(autowiringValue)) {
        // 把resolvableDependencies中保存的对象作为当前属性的一个候选者
        result.put(ObjectUtils.identityToString(autowiringValue),
          autowiringValue);
        break;
      }
    }
  }
  // 对候选bean进行过滤
  // 1、候选者不是自己,自己注入自己
  // 2、候选者是支持自动注入给其他bean的。可以在 xml 的属性设置为false。autowire-candidate="false",false:不作为候选者
  for(String candidate: candidateNames) {
    // isAutowireCandidate方法中会去判断候选者是否和descriptor匹配
    // isAutowireCandidate 这个是重点方法
    if(!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate,
        descriptor)) {
      // 类型匹配成功,将结果放入到 Map中
      addCandidateEntry(result, candidate, descriptor, requiredType);
    }
  }
  //下面这些代码可以忽略了 上面才是重点流程
  if(result.isEmpty()) {
    boolean multiple = indicatesMultipleBeans(requiredType);
    DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
    for(String candidate: candidateNames) {
      if(!isSelfReference(beanName, candidate) && isAutowireCandidate(
          candidate, fallbackDescriptor) && (!multiple ||
          getAutowireCandidateResolver().hasQualifier(descriptor))) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
      }
    }
    if(result.isEmpty() && !multiple) {
      for(String candidate: candidateNames) {
        if(isSelfReference(beanName, candidate) && (!(descriptor instanceof MultiElementDescriptor) ||
            !beanName.equals(candidate)) && isAutowireCandidate(candidate,
            fallbackDescriptor)) {
          addCandidateEntry(result, candidate, descriptor, requiredType);
        }
      }
    }
  }
  //返回结果
  return result;
}
isAutowireCandidate

继续往下看,这时候我们已经拿到了同类型的所有 beanName 了,还需要再判断一下。

@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
  // 继续往下
  return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}

继续往下

protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor,
  AutowireCandidateResolver resolver)
throws NoSuchBeanDefinitionException {
  String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
  // 判断候选者名称 在 beanDefinitionMap 是否存在
  if(containsBeanDefinition(beanDefinitionName)) {
    // 根据候选者名称获得BeanDefinition,判断是否和descriptor匹配
    return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(
      beanDefinitionName), descriptor, resolver);
  } else if(containsSingleton(beanName)) {
    // 如果没有BeanDefinition,则直接找bean对象,如果存在则和descriptor匹配
    return isAutowireCandidate(beanName, new RootBeanDefinition(getType(
      beanName)), descriptor, resolver);
  }
  // 去父BeanFactory中进行匹配
  BeanFactory parent = getParentBeanFactory();
  if(parent instanceof DefaultListableBeanFactory) {
    return((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName,
      descriptor, resolver);
  } else if(parent instanceof ConfigurableListableBeanFactory) {
    return((ConfigurableListableBeanFactory) parent).isAutowireCandidate(
      beanName, descriptor);
  } else {
    return true;
  }
}
isAutowireCandidate
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
  DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
  String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
  // 加载mbd中所指定的类(之前讲过)
  resolveBeanClass(mbd, beanDefinitionName);
  // 这个判断不知道如何才能满足 所以就不管了
  if(mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
    new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
  }
  // 检查BeanDefinitionHolder和descriptor匹配
  return resolver.isAutowireCandidate(new BeanDefinitionHolder(mbd, beanName,
    getAliases(beanDefinitionName)), descriptor);
}

这里会调用 AutowireCandidateResolver.isAutowireCandidate方法。

default boolean isAutowireCandidate(BeanDefinitionHolder bdHolder,
  DependencyDescriptor descriptor) {
  return bdHolder.getBeanDefinition().isAutowireCandidate();
}

AutowireCandidateResolver.isAutowireCandidate是默认方法。该方法下有三个子类实现:SimpleAutowireCandidateResolverGenericTypeAwareAutowireCandidateResolverQualifierAnnotationAutowireCandidateResolver

各位细心一点其实会发现:QualifierAnnotationAutowireCandidateResolver继承GenericTypeAwareAutowireCandidateResolverGenericTypeAwareAutowireCandidateResolver 继承 SimpleAutowireCandidateResolverSimpleAutowireCandidateResolver 继承 AutowireCandidateResolver

image-20210405175617479.png 我们直接进入到 QualifierAnnotationAutowireCandidateResolver类中,进入最基层。

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder,
  DependencyDescriptor descriptor) {
  // 先交给GenericTypeAwareAutowireCandidateResolver进行验证bd和descriptor是否匹配
  // 先进行其他验证,再进行Qualifiers验证
  boolean match = super.isAutowireCandidate(bdHolder, descriptor);
  // 如果某个beanDefinition和descriptor匹配,那么再判断一下是否使用了@Qualifier注解或者 xml中的 qualifier 标签
  // 如果使用了则要继续判断当前bd的beanName是否和@Qualifier注解或者 xml中的 qualifier 标签所指定的名字相等
  if(match) {
    match = checkQualifiers(bdHolder, descriptor.getAnnotations());
    if(match) {
      //如果匹配,尝试检查方法上的注解,因为可能加在方法上
      MethodParameter methodParam = descriptor.getMethodParameter();
      if(methodParam != null) {
        Method method = methodParam.getMethod();
        if(method == null || void.class == method.getReturnType()) {
          match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
        }
      }
    }
  }
  return match;
}

QualifierAnnotationAutowireCandidateResolver类的isAutowireCandidate方法首先调用父类的 super.isAutowireCandidate方法,也就是 ``GenericTypeAwareAutowireCandidateResolver

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder,
  DependencyDescriptor descriptor) {
  // 先调用SimpleAutowireCandidateResolver进行验证是否匹配
  if(!super.isAutowireCandidate(bdHolder, descriptor)) {
    // If explicitly false, do not proceed with any other checks...
    return false;
  }
  // 如果不匹配则进行泛型匹配
  return checkGenericTypeMatch(bdHolder, descriptor);
}

在此调用父类(SimpleAutowireCandidateResolver)的 isAutowireCandidate方法。

@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder,
  DependencyDescriptor descriptor) {
  return bdHolder.getBeanDefinition().isAutowireCandidate();
}

如果 autowireCandidate属性为 false,这样容器在查找自动装配对象时,将不考虑该bean。当然也就不会再执行两个子类的逻辑了。如果为 true,就分别去依次执行子类的逻辑。

到这,findAutowireCandidates方法才正式结束!感觉很复杂,总结一下findAutowireCandidates的总体流程吧!

一、根据依赖描述的类型去寻找候选者的 beanName。循环 beanDefinitionNames与类型进行匹配,将类型匹配成功的名称进行返回,这也就是byType

二、判断是否是候选者Bean,由autowireCandidate属性控制。

三、对其泛型类型进行匹配。

四、进行Qualifier验证。

五、得到Map,进行返回。


接下来就是对拿到的 Map 进行再一步的筛选。具体逻辑在 determineAutowireCandidate方法中。

determineAutowireCandidate

该方法位于DefaultListableBeanFactory类,作用是确定自动装配的候选者。

@Nullable
protected String determineAutowireCandidate(Map < String, Object > candidates,
  DependencyDescriptor descriptor) {
  Class <? > requiredType = descriptor.getDependencyType();
  // 取@Primary的bean
  String primaryCandidate = determinePrimaryCandidate(candidates,
    requiredType);
  if(primaryCandidate != null) {
    return primaryCandidate;
  }
  // 取优先级最高的bean 通过@Priority来定义优先级,数字越小,优先级越高
  String priorityCandidate = determineHighestPriorityCandidate(candidates,
    requiredType);
  if(priorityCandidate != null) {
    return priorityCandidate;
  }
  // byName
  for(Map.Entry < String, Object > entry: candidates.entrySet()) {
    String candidateName = entry.getKey();
    Object beanInstance = entry.getValue();
    if((beanInstance != null && this.resolvableDependencies.containsValue(
        beanInstance)) ||
      // 根据属性名确定
      // descriptor.getDependencyName()
      matchesBeanName(candidateName, descriptor.getDependencyName())) {
      return candidateName;
    }
  }
  return null;
}
@Primary

@Primary可以理解被标注的bean为默认优先选择,不可以同时设置多个, 其实是 BeanDefinitionprimary属性。

@Nullable
protected String determinePrimaryCandidate(Map < String, Object > candidates,
  Class <? > requiredType) {
  String primaryBeanName = null;
  // 遍历找到的候选者
  for(Map.Entry < String, Object > entry: candidates.entrySet()) {
    // beanName
    String candidateBeanName = entry.getKey();
    // 实例或者是class
    Object beanInstance = entry.getValue();
    // 当前candidateBean是否包含@Primary注解
    if(isPrimary(candidateBeanName, beanInstance)) {
      if(primaryBeanName != null) {
        // 如果多个候选者上都标注了 @Primary注解,则抛出异常
        boolean candidateLocal = containsBeanDefinition(candidateBeanName);
        boolean primaryLocal = containsBeanDefinition(primaryBeanName);
        if(candidateLocal && primaryLocal) {
          throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
            "more than one 'primary' bean found among candidates: " +
            candidates.keySet());
        } else if(candidateLocal) {
          primaryBeanName = candidateBeanName;
        }
      } else {
        primaryBeanName = candidateBeanName;
      }
    }
  }
  return primaryBeanName;
}
isPrimary
protected boolean isPrimary(String beanName, Object beanInstance) {
  String transformedBeanName = transformedBeanName(beanName);
  // beanDefinitionMap 中是否存在 transformedBeanName
  if(containsBeanDefinition(transformedBeanName)) {
    // isPrimary 是 BeanDefinition中的一个方法
    // primary为true,就代表使用了@Primary注解
    return getMergedLocalBeanDefinition(transformedBeanName).isPrimary();
  }
  BeanFactory parent = getParentBeanFactory();
  return(parent instanceof DefaultListableBeanFactory && ((
    DefaultListableBeanFactory) parent).isPrimary(transformedBeanName,
    beanInstance));
}
@Priority

@Priority它属于javax.annotationJSR250规范。通过@Priority来定义优先级,数字越小,优先级越高。

@Nullable
protected String determineHighestPriorityCandidate(Map < String, Object >
  candidates, Class <? > requiredType) {
  String highestPriorityBeanName = null;
  Integer highestPriority = null;
  // 遍历找到的候选者
  for(Map.Entry < String, Object > entry: candidates.entrySet()) {
    String candidateBeanName = entry.getKey();
    Object beanInstance = entry.getValue();
    if(beanInstance != null) {
      // 获得 beanInstance 上 @Priority注解的值
      Integer candidatePriority = getPriority(beanInstance); //@Priority(1)
      if(candidatePriority != null) {
        // 如果多个候选者上都标注了 @Priority注解,则进行比较
        // 如果相等抛出异常
        // 如果当前候选者的值小于之前候选者的值,则覆盖之前的值
        if(highestPriorityBeanName != null) {
          if(candidatePriority.equals(highestPriority)) {
            throw new NoUniqueBeanDefinitionException(requiredType,
              candidates.size(),
              "Multiple beans found with the same priority ('" +
              highestPriority + "') among candidates: " + candidates.keySet()
            );
          } else if(candidatePriority < highestPriority) {
            highestPriorityBeanName = candidateBeanName;
            highestPriority = candidatePriority;
          }
        } else {
          highestPriorityBeanName = candidateBeanName;
          // 将获取到的值先暂存起来,用于后续比较
          highestPriority = candidatePriority;
        }
      }
    }
  }
  return highestPriorityBeanName;
}
byName

至于byName,也就是以下这段代码,关注一下descriptor.getDependencyName()该方法返回的值。在讲byType的时候提到,AutowireByTypeDependencyDescriptor类中 getDependencyName方法返回 null。所以byType没办法根据byName筛选。

for(Map.Entry < String, Object > entry: candidates.entrySet()) {
  String candidateName = entry.getKey();
  Object beanInstance = entry.getValue();
  if((beanInstance != null && this.resolvableDependencies.containsValue(
      beanInstance)) ||
    // 根据属性名确定
    // descriptor.getDependencyName()
    matchesBeanName(candidateName, descriptor.getDependencyName())) {
    return candidateName;
  }
}

实例

对于 @Autowired的具体使用方式可以前往小杰的另外一篇博文进行阅读。@Autowired的使用方式

2、CommonAnnotationBeanPostProcessor

上面分析完了 AutowiredAnnotationBeanPostProcessor类,为了完整性,就不拆分文章了,进入到CommonAnnotationBeanPostProcessor类的postProcessProperties方法。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs,
  Object bean, String beanName) {
    //从缓存中获取 InjectionMetadata 对象
  InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(),
    pvs);
  try {
    //调用 inject
    metadata.inject(bean, beanName, pvs);
  }
  catch(Throwable ex) {
    throw new BeanCreationException(beanName,
      "Injection of resource dependencies failed", ex);
  }
  return pvs;
}

进入到 inject方法

public void inject(Object target, @Nullable String beanName, @
  Nullable PropertyValues pvs) throws Throwable {
    
  Collection < InjectedElement > checkedElements = this.checkedElements;
  Collection < InjectedElement > elementsToIterate = (
    checkedElements != null ? checkedElements : this.injectedElements
  );
  if(!elementsToIterate.isEmpty()) {
    // 遍历每个注入点,进行注入,注入点可以是属性、方法
    for(InjectedElement element: elementsToIterate) {
      if(logger.isTraceEnabled()) {
        logger.trace("Processing injected element of bean '" +
          beanName + "': " + element);
      }
      // element可能是Method,也可能是Field
      element.inject(target, beanName, pvs);
    }
  }
}

然后调试进入element.inject。在CommonAnnotationBeanPostProcessor类找到的注入点对象,WebServiceRefElementEjbRefElementResourceElement并没有重写父类的inject方法,所以会使用父类的 inject逻辑。

protected void inject(Object target, @Nullable String requestingBeanName, @
  Nullable PropertyValues pvs)
throws Throwable {
  // 如果是属性,则反射赋值
  if(this.isField) {
    Field field = (Field) this.member;
    ReflectionUtils.makeAccessible(field);
    field.set(target, getResourceToInject(target, requestingBeanName));
  } else {
    // 检查当前的属性是不是通过by_name和by_type来注入的
    if(checkPropertySkipping(pvs)) {
      return;
    }
    try {
      // 如果是方法,则通过方法赋值
      // 这里的方法并不是一定要setXX方法
      //@Resource
	  //private void order1(OrderService order){
	  //	this.order = order;
	  //}
      Method method = (Method) this.member;
      ReflectionUtils.makeAccessible(method);
      method.invoke(target, getResourceToInject(target,
        requestingBeanName));
    }
    catch(InvocationTargetException ex) {
      throw ex.getTargetException();
    }
  }
}

@Resource 注解逻辑放在getResourceToInject方法中,一起来看看吧!

该方法有两个参数,含义分别如下:

  • target:bean的实例对象
  • requestingBeanName:bean名称
@Nullable
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName){
  return null;
}

该方法并没有具体的逻辑,但是它有四个子类,如下图 image-20210911131421700.png

本篇只看ResourceElement中的实现。在看具体实现之前,我们先来看一下ResourceElement的构造方法。该构造方法被两个地方用到(ps:如果忘记了可以再去看看 Spring源码(十)-寻找注入点-MergedBeanDefinitionPostProcessor)。分别如下:

  • new ResourceElement(field, field, null):构建基于字段的ResourceElement的对象
  • new ResourceElement(method, bridgedMethod, pd):构建基于方法的ResourceElement的对象

ResourceElement

public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
  super(member, pd);
  //获得 Resource注解 对象
  Resource resource = ae.getAnnotation(Resource.class);
  String resourceName = resource.name();
  Class <? > resourceType = resource.type();
  // 如果@Resource注解中没有指定name,那么就使用默认生成的名字
  this.isDefaultName = !StringUtils.hasLength(resourceName);
  if(this.isDefaultName) {
    //属性名称 或者 方法名称
    resourceName = this.member.getName();
    //对方法名称进行截取
    if(this.member instanceof Method && resourceName.startsWith(
        "set") && resourceName.length() > 3) {
      resourceName = Introspector.decapitalize(resourceName.substring(
        3));
    }
  } else if(embeddedValueResolver != null) {
    // 占位符填充
    resourceName = embeddedValueResolver.resolveStringValue(
      resourceName);
  }
  //检查类型是否匹配。默认值就是 Object
  if(Object.class != resourceType) {
    checkResourceType(resourceType);
  } else {
    // No resource type specified... check field/method.
    resourceType = getResourceType();
  }
  //进行赋值
  this.name = (resourceName != null ? resourceName : "");
  this.lookupType = resourceType;
  String lookupValue = resource.lookup();
  this.mappedName = (StringUtils.hasLength(lookupValue) ?
    lookupValue : resource.mappedName());
  //从这里看到  @Resource 是可以同 @Lazy 一起使用的
  Lazy lazy = ae.getAnnotation(Lazy.class);
  this.lazyLookup = (lazy != null && lazy.value());
}
  • checkResourceType
protected final void checkResourceType(Class <? > resourceType) {
  if(this.isField) {
    //得到@Resourec注解标注字段的类型
    Class <? > fieldType = ((Field) this.member).getType();
    //isAssignableFrom:判断是否为某个类的父类
    //resourceType值为 @Resource注解中 type 属性的值
    //这里控制 @Resource 注解中 type 属性的值不能随便填
    if(!(resourceType.isAssignableFrom(fieldType) || fieldType.isAssignableFrom(
        resourceType))) {
      throw new IllegalStateException("Specified field type [" +
        fieldType + "] is incompatible with resource type [" +
        resourceType.getName() + "]");
    }
  } else {
    //拿到方法参数 ,参数个数只能为一个
    Class <? > paramType = (this.pd != null ? this.pd.getPropertyType() :
      ((Method) this.member).getParameterTypes()[0]);
    //与上述逻辑一致
    if(!(resourceType.isAssignableFrom(paramType) || paramType.isAssignableFrom(
        resourceType))) {
      throw new IllegalStateException("Specified parameter type [" +
        paramType + "] is incompatible with resource type [" +
        resourceType.getName() + "]");
    }
  }
}

上述逻辑在执行解析注入点的时候就会被执行。现在我们就来看看是如何进行属性注入的吧!

@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName){
  return(this.lazyLookup ? buildLazyResourceProxy(this,
    requestingBeanName) : getResource(this, requestingBeanName));
}

三元运算表达式。如果 lazyLookuptrue 则执行 buildLazyResourceProxy方法,否则执行getResource方法。默认是 false,当然可以 @Reource可以配置@Lazy共同使用。不过无论是 lazyLookuptrue 还是为false, 都会调用 getResource方法。

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
  if(StringUtils.hasLength(element.mappedName)) {
    return this.jndiFactory.getBean(element.mappedName, element.lookupType);
  }
  if(this.alwaysUseJndiLookup) {
    return this.jndiFactory.getBean(element.name, element.lookupType);
  }
  if(this.resourceFactory == null) {
    throw new NoSuchBeanDefinitionException(element.lookupType,
      "No resource factory configured - specify the 'resourceFactory' property"
    );
  }
  return autowireResource(this.resourceFactory, element,
    requestingBeanName);
}

如果@Resource注解配置了 lookupmappedName的值,那么就会去 SimpleJndiBeanFactory 工厂里面去找Bean,没有配置,则调用autowireResource方法。对于 Jndi的相关写法、源码本文不再探讨,知道 @Resource注解是支持JNDI工厂就行。

protected Object autowireResource(BeanFactory factory, LookupElement element, @
  Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
  Object resource;
  Set < String > autowiredBeanNames;
  String name = element.name;
  if(factory instanceof AutowireCapableBeanFactory) {
    AutowireCapableBeanFactory beanFactory = (
      AutowireCapableBeanFactory) factory;
    //构建依赖描述信息
    //可以是 属性字段、方法参数
    DependencyDescriptor descriptor = element.getDependencyDescriptor();
    // fallbackToDefaultTypeMatch 默认为 true
    // 如果@Resource 没有配置 name 属性, isDefaultName为true
    // 如果配置了 @Resource(name = "sfe")  isDefaultName为false
    // factory.containsBean 会进入到 AbstractBeanFactory 类的 containsBean 方法,这也就是 @Resource 的 byName
    if(this.fallbackToDefaultTypeMatch && element.isDefaultName && !
      factory.containsBean(name)) {
      autowiredBeanNames = new LinkedHashSet < > ();
      //调用  resolveDependency 方法
      resource = beanFactory.resolveDependency(descriptor,
        requestingBeanName, autowiredBeanNames, null);
      if(resource == null) {
        throw new NoSuchBeanDefinitionException(element.getLookupType(),
          "No resolvable resource object");
      }
    } else {
      //内部调用 getBean 方法
      resource = beanFactory.resolveBeanByName(name, descriptor);
      autowiredBeanNames = Collections.singleton(name);
    }
  } 
    //以下逻辑忽略
    else {
    resource = factory.getBean(name, element.lookupType);
    autowiredBeanNames = Collections.singleton(name);
  }
  if(factory instanceof ConfigurableBeanFactory) {
    ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
    for(String autowiredBeanName: autowiredBeanNames) {
      if(requestingBeanName != null && beanFactory.containsBean(
          autowiredBeanName)) {
        beanFactory.registerDependentBean(autowiredBeanName,
          requestingBeanName);
      }
    }
  }
  return resource;
}

首先判断当前 factory是不是 AutowireCapableBeanFactory ,一般来说这个条件都是满足的。然后获得依赖描述信息(是不是有点熟悉了),然后有一个 if/else, 为 true 调用 resolveDependency方法。为 false调用resolveBeanByName方法。

哦豁,如果为 true 调用 resolveDependency方法 ,那么@Resource注解逻辑不就和@Autowired一样吗?

不知道各位小伙伴有没有注意 if()语句中有一个判断条件为: factory.containsBean(name),作用是判断当前容器中是否包含指定名称的 Bean。这就是 byName的逻辑。

如果``factory.containsBean(name)返回 true,也就是包含此名称的 Bean,则进入else块逻辑,调用 resolveBeanByName方法,内部调用 getBean`方法。

如果``factory.containsBean(name)返回 false,则调用 resolveDependency方法,进行 byType@Qualifier@Primary@Priority`一系列吧啦吧啦的。


到这里完成了所有注入属性的获取,将获取的属性封装在 PropertyValues 的实例对象 pvs 中,但并没有应用到已经实例化的bean 中。注解方式除外,解析完之后被反射设值了。下面分析populateBean方法的最后一步:applyPropertyValues()

applyPropertyValues

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // pvs为空列表 ,直接返回(注解开发)
    // 1、pvs的值来源于 在xml中配置了 property 属性
    // 2、根据 byType、byName 自动注入,会将找到的对象添加到 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 {
                // 设置属性值
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        
        original = mpvs.getPropertyValueList();
    } else {
        // 如果 pvs 不是 MutablePropertyValues 类型,则直接使用原始类型
        original = Arrays.asList(pvs.getPropertyValues());
    }
    // 获取 TypeConverter
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    // 获取对应的解析器
    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();
            if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                //获得指定名称的set方法
                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);
            }
            //是否需要解析,获得Bean实例
            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);
            }
            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) {
        //converted 设置为 true,作为缓存
        mpvs.setConverted();
    }

    try {
        // 设置值 执行set方法
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

到此,Spring 的属性填充到此结束了。


  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。