Spring源码:属性填充-populateBean

前言

如果不是通过构造方法进行属性赋值的话,那实例化的对象中的属性的值都是 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");
      }
    }
  }
}
复制代码

可以看到 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存的可以是

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值