二十三、创建Bean之属性填充
doCreateBean(...)
方法,主要用于完成 bean 的创建和初始化工作,我们可以将其分为四个过程:
createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
方法,实例化 bean 。- 循环依赖的处理。
populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
方法,进行属性填充。initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
方法,初始化 Bean 。
populateBean()
方法
该函数的作用是将 BeanDefinition 中的属性值赋值给 BeanWrapper 实例对象。
1 |
|
处理过程如下:
<1>
,根据hasInstantiationAwareBeanPostProcessors
属性来判断,是否需要在注入属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会。此过程可以控制 Spring 是否继续进行属性填充。统一存入到 PropertyValues 中,PropertyValues 用于描述 bean 的属性。
<2>
,根据注入类型(AbstractBeanDefinition.getResolvedAutowireMode()
方法的返回值 )的不同来判断:是根据名称来自动注入(autowireByName(…)),还是根据类型来自动注入(autowireByType(…))。
<3>
,进行 BeanPostProcessor 处理。<4>
,依赖检测。<5>
,将所有 PropertyValues 中的属性,填充到 BeanWrapper 中。
自动注入
Spring 会根据注入类型( byName
/ byType
)的不同,调用不同的方法来注入属性值。
1 |
|
autowireByName()
方法
该方法,是根据属性名称,完成自动依赖注入的。
1 |
|
<1>
处,获取该 bean 的非简单属性。非简单属性就是类型为对象类型的属性,但是这里并不是将所有的对象类型都都会找到,比如 8 个原始类型,String 类型 ,Number类型、Date类型、URL类型、URI类型等都会被忽略。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
// 创建 result 集合
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
// 遍历 PropertyDescriptor 数组
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null // 有可写方法
&& !isExcludedFromDependencyCheck(pd) // 依赖检测中没有被忽略
&& !pvs.contains(pd.getName()) &&// pvs 不包含该属性名
!BeanUtils.isSimpleProperty(pd.getPropertyType())) { // 不是简单属性类型
result.add(pd.getName());// 添加到 result 中
}
}
return StringUtils.toStringArray(result);
}- 过滤条件为:有可写方法、依赖检测中没有被忽略、不是简单属性类型。
- 过滤结果为:其实这里获取的就是需要依赖注入的属性。
<2>处,获取需要依赖注入的属性后,通过迭代、递归的方式初始化相关的 bean ,然后调用
registerDependentBean(String beanName, String dependentBeanName)
方法,完成注册依赖。该方法之前《parentBeanFactory和依赖处理》已经分析过了。
autowireByType()
方法
该方法,是根据属性类型,完成自动依赖注入的。
1 |
|
其实主要过程和根据名称自动注入差不多,都是找到需要依赖注入的属性,然后通过迭代的方式寻找所匹配的 bean,最后调用 registerDependentBean(...)
方法,来注册依赖。
**resolveDependency()**方法。
1 |
|
通用处理逻辑doResolveDependency()
:
1 |
|
到这里就已经完成了所有属性的注入了。
- 下一步,则是对依赖 bean 的依赖检测和 PostProcessor 处理(该分析放在最后)。
- 最后一步:
applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)
方法。
applyPropertyValues()
方法
上面只是完成了所有注入属性的获取,将获取的属性封装在 PropertyValues 的实例对象 pvs
中,并没有应用到已经实例化的 bean 中。该方法是populateBean()
的最后一步<5>,将属性添加到Bean。
1 |
|
以上完成了属性转换:
- 属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。
- 属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。
其中调用了 resolveValueIfNecessary(...)
方法对属性值的解析。