该系列文章是本人在学习 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.javaprotected 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> 遍历所有的 BeanPostProcessorfor (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();// 是否需要进行依赖检查,默认为 trueboolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;// <5> 通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 `pvs` 进行处理if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// <5.1> 遍历所有的 BeanPostProcessorfor (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
(允许对属性进行相关操作)
newPvs
中,调用
autowireByName(...)
方法
newPvs
中,调用
autowireByType(...)
方法
newPvs
复制给
pvs
通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对
pvs
进行处理
- 遍历所有的 BeanPostProcessor
postProcessProperties(...)
方法,对
pvs
进行后置处理
java.beans.PropertyDescriptor
属性描述器(包含这个属性的所有信息)
postProcessPropertyValues(...)
方法,对
pvs
进行后置处理
return
,则不会调用后面的处理器,也不会进行接下来的属性填充
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.javaprotected 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.javaprotected 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.javaprotected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {// <1> 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器// 例如 Spring 3.0 之后的 ConversionServiceTypeConverter 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.javaprotected 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 之后的 ConversionServiceTypeConverter 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
集合中
[ol]
属性值已经转换了,则将这些属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!!
调用
BeanWrapperImpl#setPropertyValues(PropertyValues)
方法
-
没有转换过,则获取所有的属性值集合,放入
original
集合中
定义一个
deepCopy
集合,保存转换后的属性值
遍历所有的属性值,进行转换(如果有必要)
- 已经转换过,则直接添加到
deepCopy
中
${systenm.user}
,则会解析出对应的值
deepCopy
中
[/ol]
如果属性值不为空,且不需要每次都处理,则设置为已转换
将属性值设置到当前 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 等注解的实现原理》文章中进行分析