死磕Spring之IoC篇 - Bean 的属性填充阶段
该系列文章是本人在学习 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
进行处理- 遍历所有的 BeanPostProcessor
- 如果为 InstantiationAwareBeanPostProcessor 类型,则调用其
postProcessProperties(...)
方法,对pvs
进行后置处理 - 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本
- 尝试找到这个 Bean 的所有
java.beans.PropertyDescriptor
属性描述器(包含这个属性的所有信息) - 调用处理器的
postProcessPropertyValues(...)
方法,对pvs
进行后置处理 - 如果处理后的 PropertyValues 对象为空,直接
return
,则不会调用后面的处理器,也不会进行接下来的属性填充
- 尝试找到这个 Bean 的所有
- 将处理后的
pvsToUse
复制给pvs
-
依赖检查
- 找到这个 Bean 的所有
java.beans.PropertyDescriptor
属性描述器(包含这个属性的所有信息) - 进行依赖检查,如果没有找到对应的属性值,则根据检查策略进行抛出异常(默认不会)
- 找到这个 Bean 的所有
-
如果
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
集合,保存转换后的属性值 -
遍历所有的属性值,进行转换(如果有必要)
- 已经转换过,则直接添加到
deepCopy
中 - 否则,开始进行转换
- 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为
${systenm.user}
,则会解析出对应的值 - 使用类型转换器转换属性值(如果有必要的话)
- 设置转换后的值,避免上面的各种判断
- 添加到
deepCopy
中
- 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为
- 已经转换过,则直接添加到
-
如果属性值不为空,且不需要每次都处理,则设置为已转换
-
将属性值设置到当前 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 等注解的实现原理》文章中进行分析