该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读
Spring 版本:5.1.14.RELEASE
开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》这一篇文章
该系列其他文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》
Bean 的属性填充阶段
当我们显示或者隐式地调用AbstractBeanFactory 的 getBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》文章中分析了整个加载过程。
对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactory 的 createBean(...) 方法进行创建,在《Bean 的创建过程》文章中分析了整个创建过程。创建 Bean 的过程中,在获取到的一个实例对象后,里面的相关属性也许是空的,那么接下来要做的就是将需要填充的属性进行依赖注入,然后再进行后续的初始化工作。整个的属性填充过程非常复杂,因为配置的属性值可能是一个表达式,需要解析,类型也可能不对,需要进行类型转换,还可能是一个对象,需要找到对应的 Bean 然后注入(依赖注入),存在有各种处理,本文将会分析创建 Bean 过程中的属性填充阶段。
回顾
先来回顾一下创建 Bean 过程中属性填充阶段对应的代码:
// AbstractAutowireCapableBeanFactory#doCreateBean(...) 方法 // Initialize the bean instance. // 开始初始化 `bean` Object exposedObject = bean; try { // <4> 对 `bean` 进行属性填充,注入对应的属性值 populateBean(beanName, mbd, instanceWrapper); // <5> 初始化这个 `exposedObject`,调用其初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } }
在创建好实例对象后,这个对象的属性还没有赋值,所以将这个实例对象的相关属性进行赋值,也就是上面的第 <4> 步
开启 Bean 的属性填充
populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 方法,属性填充,如下:
// AbstractAutowireCapableBeanFactory.java protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // <1> 如果实例对象为空,则进行下面的判断 if (bw == null) { // <1.1> 这个 Bean 有属性,则抛出异常 if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } // <1.2> 否则,不用属性填充,直接 `return` else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. // <2> 实例化阶段的后置处理,如果满足这两个条件 if (!mbd.isSynthetic() // RootBeanDefinition 不是用户定义的(由 Spring 解析出来的) && hasInstantiationAwareBeanPostProcessors()) { // 是否有 InstantiationAwareBeanPostProcessor 处理器 // <2.1> 遍历所有的 BeanPostProcessor for (BeanPostProcessor bp : getBeanPostProcessors()) { // 如果为 InstantiationAwareBeanPostProcessor 类型 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // <2.2> 对实例化对象进行后置处理 // 注意如果返回 false,直接 `return`,不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // <3> 获取 `pvs`,承载当前对象的属性值 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // <4> 获取这个 Bean 的注入模式,默认为 **AUTOWIRE_NO**,例如可以通过 `@Bean` 注解的 `autowire` 属性配置注入模式 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); // <4.1> 如果注入模式为 **AUTOWIRE_BY_NAME** 或者 **AUTOWIRE_BY_TYPE**,则通过下面的方式获取属性值 if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { // <4.2> 将 `pvs` 封装成 MutablePropertyValues 对象 `newPvs`(允许对属性进行相关操作) MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. // <4.3> **AUTOWIRE_BY_NAME** 模式,通过名称获取相关属性值,保存在 `newPvs` 中 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. // <4.4> **AUTOWIRE_BY_TYPE** 模式,通过类型获取相关属性值,保存在 `newPvs` 中 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } // <4.5> 将 `newPvs` 复制给 `pvs` pvs = newPvs; } // 是否有 InstantiationAwareBeanPostProcessor 处理器 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否需要进行依赖检查,默认为 true boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; // <5> 通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 `pvs` 进行处理 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // <5.1> 遍历所有的 BeanPostProcessor for (BeanPostProcessor bp : getBeanPostProcessors()) { // 如果为 InstantiationAwareBeanPostProcessor 类型 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; /** * Spring 内部的 InstantiationAwareBeanPostProcessor 处理器: * {@link AutowiredAnnotationBeanPostProcessor#postProcessProperties} 会解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值; * {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties} 会解析 @Resource 注解标注的属性,获取对应的属性值 */ // <5.2> 调用处理器的 `postProcessProperties(...)` 方法,对 `pvs` 进行后置处理 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); // <5.3> 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本 if (pvsToUse == null) { // <5.3.1> 找到这个 Bean 的所有 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息) if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // <5.3.2> 调用处理器的 `postProcessPropertyValues(...)` 方法,对 `pvs` 进行后置处理 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); // <5.3.3> 如果处理后的 PropertyValues 对象为空,直接 `return`,则不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充 if (pvsToUse == null) { return; } } // <5.4> 将处理后的 `pvsToUse` 复制给 `pvs` pvs = pvsToUse; } } } // <6> 依赖检查 if (needsDepCheck) { // <6.1> 找到这个 Bean 的所有 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息) if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // <6.2> 依赖检查,如果没有找到对应的属性值,则根据检查策略进行抛出异常(默认不会) checkDependencies(beanName, mbd, filteredPds, pvs); } // <7> 如果 `pvs` 不为空,则将里面的属性值设置到当前 Bean 对应的属性中(依赖注入) // 前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
过程大致如下:
如果实例对象为null,则进行下面的判断
- 这个 Bean 有属性,则抛出异常
- 否则,不用属性填充,直接 return
实例化阶段的后置处理,如果满足这两个条件:RootBeanDefinition 不是用户定义的(由 Spring 解析出来的)、是否有 InstantiationAwareBeanPostProcessor 处理器
遍历所有的 BeanPostProcessor
如果为 InstantiationAwareBeanPostProcessor 类型,则对实例化对象进行后置处理
注意,如果返回 false,直接 return,不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充
获取 pvs,承载当前对象的属性值
获取这个 Bean 的注入模式,默认为 AUTOWIRE_NO,例如可以通过 @Bean 注解的 autowire 属性配置注入模式
- 如果注入模式为 AUTOWIRE_BY_NAME 或者 AUTOWIRE_BY_TYPE,则通过下面的方式获取属性值
- 将 pvs 封装成 MutablePropertyValues 对象 newPvs(允许对属性进行相关操作)
- AUTOWIRE_BY_NAME 模式,通过名称获取相关属性值,保存在 newPvs 中,调用 autowireByName(...) 方法
- AUTOWIRE_BY_TYPE 模式,通过类型获取相关属性值,保存在 newPvs 中,调用 autowireByType(...) 方法
- 将 newPvs 复制给 pvs
通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 pvs 进行处理
- 尝试找到这个 Bean 的所有 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
- 调用处理器的 postProcessPropertyValues(...) 方法,对 pvs 进行后置处理
- 如果处理后的 PropertyValues 对象为空,直接 return,则不会调用后面的处理器,也不会进行接下来的属性填充
- 遍历所有的 BeanPostProcessor
- 如果为 InstantiationAwareBeanPostProcessor 类型,则调用其 postProcessProperties(...) 方法,对 pvs 进行后置处理
- 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本
- 将处理后的 pvsToUse 复制给 pvs
依赖检查
- 找到这个 Bean 的所有 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
- 进行依赖检查,如果没有找到对应的属性值,则根据检查策略进行抛出异常(默认不会)
如果 pvs 不为空,则将里面的属性值设置到当前 Bean 对应的属性中(依赖注入),调用 applyPropertyValues(...) 方法
前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中
整个的属性填充过程非常的复杂,接下来进行概括:
- 允许你对实例化对象进行后置处理,处理结果为 false 表示不需要进行接下来的属性填充过程
- 根据注入模式,找到没有配置属性值的对象属性,然后找到对应的 Bean,默认注入模式为不注入
- 允许你对属性值进行后置处理,例如 @Autowired、@Value 等注解标注的属性会通过这里找到对应的属性值(或对象)
- 上述过程仅找到了属性值,还没设置到当前实例对象中,所以最后一步才是真正的属性填充
上面有两种注入模式:AUTOWIRE_BY_NAME 和 AUTOWIRE_BY_TYPE,默认为 AUTOWIRE_NO,接下来先来看看这两种注入模式的实现
通过名称获取属性值
autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) 方法,通过名称获取相关属性值,如下:
// AbstractAutowireCapableBeanFactory.java protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // <1> 获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); // <2> 遍历这些对象属性的名称 for (String propertyName : propertyNames) { // <3> 如果当前容器存在对应的 Bean(通过名称判断) if (containsBean(propertyName)) { // <3.1> 根据属性名称获取对应的 `bean` 对象(依赖查找) Object bean = getBean(propertyName); // <3.2> 将 `bean` 添加至 `pvs` pvs.add(propertyName, bean); // <3.3> 将两个 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"); } } } }
过程并不复杂,大致如下:
获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性,如下:
// AbstractAutowireCapableBeanFactory.java protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { Set<String> result = new TreeSet<>(); // 获取已设置的属性值 PropertyValues pvs = mbd.getPropertyValues(); // 找到这个 Bean 的所有 PropertyDescriptor 属性描述器(包含这个属性的所有信息) PropertyDescriptor[] pds = bw.getPropertyDescriptors(); // 遍历所有属性 for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null // 有可写方法 && !isExcludedFromDependencyCheck(pd) // 不忽略 && !pvs.contains(pd.getName()) // 没有对应的属性值 && !BeanUtils.isSimpleProperty(pd.getPropertyType())) // 不是简单类型(例如一个实体类) { result.add(pd.getName()); } } // 返回这些不满意的非简单类型的属性 return StringUtils.toStringArray(result); }
遍历这些对象属性的名称
如果当前容器存在对应的 Bean(通过名称判断)
- 根据属性名称获取对应的 bean 对象(依赖查找)
- 将 bean 添加至 pvs
- 将两个 Bean 之间的依赖关系保存起来
直接根据"对象"名称通过 getBean(String beanName) 获取到对应的对象(依赖查找)
通过类型获取属性值
autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) 方法,通过类型获取相关属性值,如下:
// AbstractAutowireCapableBeanFactory.java protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { // <1> 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器 // 例如 Spring 3.0 之后的 ConversionService TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<>(4); // <2> 获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); // <3> 遍历这些对象属性的名称 for (String propertyName : propertyNames) { try { // <3> 获取这个属性的 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息) PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); // <4> 如果不是 Object 类型(对 Object 类类型的 Bean 进行自动装配毫无意义),则尝试找到对应的对象 if (Object.class != pd.getPropertyType()) { // <5> 找到这个属性的写方法 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); // Do not allow eager init for type matching in case of a prioritized post-processor. // 是否可以提前初始化 boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered); // <6> 创建对应的依赖注入描述对象 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); // <7> 依赖注入,找到该属性对应的对象 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); // <8> 如果找到属性对象,则将该其添加至 `pvs` if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument); } // <9> 将注入的属性对象和当前 Bean 之前的关系保存起来 // 因为该属性可能是一个集合,找到了多个对象,所以这里是一个数组 for (String autowiredBeanName : autowiredBeanNames) { // 将 `autowiredBeanName` 与 `beanName` 的依赖关系保存 registerDependentBean(autowiredBeanName, beanName); if (logger.isTraceEnabled()) { logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'"); } } // 清空 `autowiredBeanName` 数组 autowiredBeanNames.clear(); } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex); } } }
过程大致如下:
- 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器
- 获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性,和通过名称注入的过程一样
- 遍历这些"对象"属性的名称,获取这个属性的 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
- 如果不是 Object 类型(对 Object 类类型的 Bean 进行自动装配毫无意义),则尝试找到对应的对象
- 找到这个属性的写方法
- 创建对应的 DependencyDescriptor 依赖注入描述对象,默认 required 为 false,表示找不到也没关系
- 依赖注入,找到该属性对应的对象,调用 resolveDependency(...) 方法
- 如果找到属性对象,则将该其添加至 pvs
- 将注入的属性对象和当前 Bean 之前的关系保存起来
根据"对象"名称通过 resolveDependency(...) 获取到对应的对象,该方法就是依赖注入的底层实现,整个过程也非常复杂,所以将这部分内容放在下一篇《@Autowired 等注解的实现原理》文章中
属性值的后置处理
调用 InstantiationAwareBeanPostProcessor#postProcessProperties 方法,对前面属性值进行处理
在前面的AUTOWIRE_BY_NAME 和 AUTOWIRE_BY_TYPE两种注入模式中,找到的都是普通对象的属性值,例如 @Autowired、@Value 和 @Resource 注解并没有被解析,且默认的注入模式还是AUTOWIRE_NO,那这些注解是如何被解析的呢?Spring 内部有下面两个 InstantiationAwareBeanPostProcessor 处理器:
- AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
- CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值
这里先提一下,具体的实现过程在下一篇《@Autowired 等注解的实现原理》文章中进行分析
属性填充
applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) 方法,属性填充
如果获取到的 pvs 属性值对象不为空,则将里面的属性值设置到当前 Bean 对应的属性中(依赖注入),我们知道前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中,方法如下:
// AbstractAutowireCapableBeanFactory.java protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // <1> 没有相关属性值,则直接 `return` 返回 if (pvs.isEmpty()) { return; } if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); } // ------------------------开始属性值的转换与填充------------------------ MutablePropertyValues mpvs = null; // 定义一个 `original` 集合,承载属性值(未进行转换) List<PropertyValue> original; // <2> 如果 `pvs` 是 MutablePropertyValues 类型,则可能已经处理过了 if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { // <2.1> 属性值已经转换了,则将这些属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!! bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } // <2.2> 没有转换过,则获取所有的属性值集合 original = mpvs.getPropertyValueList(); } else { // <2.2> 获取所有的属性值集合 original = Arrays.asList(pvs.getPropertyValues()); } // 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器 // 例如 Spring 3.0 之后的 ConversionService TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 获取对应的解析器 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. // <3> 定义一个 `deepCopy` 集合,保存转换后的属性值 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; // <4> 遍历所有的属性值,进行转换(如果有必要) for (PropertyValue pv : original) { // <4.1> 已经转换过,则直接添加到 `deepCopy` 中 if (pv.isConverted()) { deepCopy.add(pv); } // <4.2> 否则,开始进行转换 else { String propertyName = pv.getName(); // 转换之前的属性值 Object originalValue = pv.getValue(); // <4.2.1> 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为 `${systenm.user}`,则会解析出对应的值 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); // 转换之后的属性值 Object convertedValue = resolvedValue; // 该属性是否可以转换 boolean convertible = bw.isWritableProperty(propertyName) && // 属性可写 !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); // 不包含 `.` 和 `[` if (convertible) { // <4.2.2> 使用类型转换器转换属性值(如果有必要的话) convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { // 属性值没有转换过 if (convertible) { // <4.2.3> 设置转换后的值,避免上面的各种判断 pv.setConvertedValue(convertedValue); } // <4.2.4> 添加到 `deepCopy` 中 deepCopy.add(pv); } // 属否则属性值进行了转换 else if (convertible // 可转换的 && originalValue instanceof TypedStringValue // 属性原始值是字符串类型 && !((TypedStringValue) originalValue).isDynamic() // 属性的原始类型值不是动态生成的字符串 && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) // 属性的原始值不是集合或者数组类型 { // <4.2.3> 设置转换后的值,避免上面的各种判断 pv.setConvertedValue(convertedValue); // <4.2.4> 添加到 `deepCopy` 中 deepCopy.add(pv); } // 否则 else { // 这个属性每次都要处理,不能缓存 resolveNecessary = true; // <4.2.4> 添加到 `deepCopy` 中 deepCopy.add(new PropertyValue(pv, convertedValue)); } } } // <5> 如果属性值不为空,且不需要每次都处理,则设置为已转换 if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { // <6> 将属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!! bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
过程大致如下:
- 没有相关属性值,则直接 return 返回
开始属性值的转换与填充,先定义一个 original 集合,承载属性值(未进行转换)
如果 pvs 是 MutablePropertyValues 类型,则可能已经处理过了,否则,获取所有的属性值集合,放入 original 集合中
属性值已经转换了,则将这些属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!!
调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法
没有转换过,则获取所有的属性值集合,放入 original 集合中
定义一个 deepCopy 集合,保存转换后的属性值
遍历所有的属性值,进行转换(如果有必要)
- 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为 ${systenm.user},则会解析出对应的值
- 使用类型转换器转换属性值(如果有必要的话)
- 设置转换后的值,避免上面的各种判断
- 添加到 deepCopy 中
- 已经转换过,则直接添加到 deepCopy 中
- 否则,开始进行转换
如果属性值不为空,且不需要每次都处理,则设置为已转换
将属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!!
调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法
整个属性注入过程非常复杂,上面仅列出了关键步骤,可以看到最终会调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法将属性值设置到 Bean 中
在 Bean 的实例化阶段获取到的就是一个 BeanWrapperImpl 对象,所以这里调用的就是当前 Bean 的 setPropertyValues(PropertyValues) 方法,该方法的底层借助于 Java Beans 的 java.beans.PropertyDescriptor 属性描述器,获取到对应的写方法,然后通过反射机制设置当前 Bean 的属性值
总结
当我们显示或者隐式地调用AbstractBeanFactory 的 getBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》文章中分析了整个加载过程。
对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactory 的 createBean(...) 方法进行创建,在《Bean 的创建过程》文章中分析了整个创建过程。创建 Bean 的过程中,在获取到的一个实例对象后,需要获取相关属性值,然后注入到 Bean 中,其中获取属性值有三种模式:
AUTOWIRE_NO,默认,不获取相关属性值
AUTOWIRE_BY_NAME,通过名称获取没有定义属性值的"对象"的属性值,通过 getBean(String beanName) 查找
AUTOWIRE_BY_TYPE,通过类型获取没有定义属性值的"对象"的属性值,依赖注入的方式
默认情况下,获取到已定义的属性值后不会通过上面的方式去找属性值,在后续有一个属性值的后置处理,会调用所有的 InstantiationAwareBeanPostProcessor 处理器的 postProcessProperties 方法进行处理,例如 Spring 内部有两个 InstantiationAwareBeanPostProcessor 处理器:
- AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
- CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值
在获取到所有的属性值后然后通过反射机制设置到 Bean 中
关于 @Autowired、@Value 和 @Resource 注解的实现原理将在下一篇《@Autowired 等注解的实现原理》文章中进行分析