Spring 中 applyPropertyValues 源码详解

1,025 阅读3分钟

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

1. 前言

主要作用:应用给定的属性值,解析此bean工厂中对其他bean的任何运行时引用。必须使用深层复制,所以我们不会永久修改这个属性

org.springframework.context.support.AbstractApplicationContext#refresh --》 org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization --》 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons --》 org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String) --》 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]) --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean --》 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues

2. 源码讲解

老样子,这个方法源码还是比较长,这里我们还是一段一段看

2.1 第一部分

这里的pvs ,实际上在前面讲的 populateBean 方法中的 autowireByName,autowireByType等方法都会把找到的属性和对象放入到pvs的propertyValueList,然后在调用当前方法。 图片.png

  • 这里首先判断,当pvs为null时,则说明没有需要注入给当前bean 的值,直接返回即可。

  • 当系统有安全策略管理器的时候,且bw 是 BeanWrapperImpl 的实例,则把工厂的访问控制上下文设为bw的安全上下文。(ps: Spring 默认的 BeanWrapper 实现类就是 BeanWrapperImpl)

    • getAccessControlContext : 获取当前工厂的访问控制上下文 图片.png
  • MutablePropertyValues 是 PropertyValues 的默认实现类,它允许简单的属性操作,并提供构造函数来支持从Map进行深度复制和构造。

  • orginal : 记录原始的属性和列表

2.2 第二部分

图片.png

  • 当 pvs 是 MutablePropertyValues 的实例时,把pvs 强转成 MutablePropertyValues。(通常默认pvs就是 MutablePropertyValues 类型的)

    • mpvs.isConverted(): 返回当前 MutablePropertyValues 是否仅包含转换后的值,(如果还有需要转换的值,返回false)
    • 如果当前 MutablePropertyValues 仅包含转换后的值,则直接把它赋给 bw ,返回即可。
    • 否则的话,把 mpvs 的 propertyValueList 赋给 original
  • 否则的话, 直接获取 pvs 的 PropertyValue[]并转成list 赋给 original

  • getCustomTypeConverter : 获取自定义的类型转换器,若是它为null 则把 bw(BeanWrapper 它也实现了 TypeConverter) 赋给 converter

  • BeanDefinitionValueResolver:在bean工厂实现中使用的Helper类,解析bean定义对象中包含的值,转换为应用于目标bean实例的实际值。 图片.png

2.3 第三部分

看上面的注释也说了,这部分代码的主要作用就是:创建深拷贝,解决值的任何引用 图片.png

  • 首先通过前面 original 的大小,创建一个记录需要深拷贝的属性值的 list
  • resolveNecessary : 是否需要解析
  • 遍历 original ,当取出的元素 pv 仅包含转换后的值(即不需要转换),则把它加入 deepCopy
  • 否则的话,继续向下处理
    • 获取属性名 propertyName,获取属性值 originalValue. 图片.png
    • AutowiredPropertyMarker.INSTANCE : 标记 需要 autowired 注入的值的规范实例
    • 如果 originalValue == AutowiredPropertyMarker.INSTANCE 即需要 autowired 注入。
      • 先通过 属性名propertyName 获取当前bean 的属性描述符,然后获取当前属性的 写方法
      • 若没有写方法,直接抛异常;为指定方法创建一个新的 MethodParameter(封装方法参数规范的Helper类),然后 为前面创建的 MethodParameter 参数创建新的描述符 (将依赖项视为“eager”),把它赋给 originalValue
    • 调用 resolveValueIfNecessary 解析 originalValue 并赋给 resolvedValue。
    • 创建一个 resolvedValue 的副本 convertedValue
    • isWritableProperty: 判断指定属性是不是可写的 图片.png
    • PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName) : 检查指定属性是否是索引属性或者嵌套属性
    • caonvertible : 可转换标记
    • 如果需要转换的话,则调用 转换该属性值,并赋给 convertedValue
    • convertForProperty:转换指定目标属性的给定值。 图片.png
    • 判断解析后的 resolvedValue 和 originalValue 是否相等
    • 当它们是相等的
      • 如果是可转换的,则设置 pv 的转换值
      • setConvertedValue :设置此属性值的转换值,在处理类型转换之后。 图片.png
      • 把当前的pv添加到 deepCopy 中去
    • 或者 caonvertible = true 可转换的 && originalValue 是 TypedStringValue 实例 && originalValue不是动态的 && (它是集合或数组)。
      • 调用 setConvertedValue
      • 把当前的pv添加到 deepCopy 中去
    • 否则
      • 标记是否需要解析 为true
      • 通过 pv 和 处理后的值 convertedValue 创建一个新的 PropertyValue 实例,并加到 deepCopy中去

2.4 第四部分

图片.png

  • 当mpvs 不为null && resolveNecessary == false,则调用 setConverted,将这个mpvs 标记 不在需要运行时解析 图片.png
  • 用处理后的 deepCopy 创建 MutablePropertyValues实例 设置给bw