「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
1.前言
populateBean :使用来自bean definition 的属性值在给定的BeanWrapper中填充bean实例。
这个方法在spring 容器初始化调用的位置: 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
2.populateBean 源码
鉴于这个方法比较长,所以这里我们还是一块一块的讲
2.1 跳过null bean 的属性注入
- 首先它会判断这个 BeanWrapper(bw)是不是null,
- mbd.hasPropertyValues():如果有给该bean定义的属性值,则返回
- 当 bw 是null时,应该不能有为该bean 定义的属性值,有的话抛出异常
- 没有的话,则跳过null 实例的属性解析
2.2 给 InstantiationAwareBeanPostProcessors 最后一次机会在属性注入前修改Bean的属性值
- continueWithPropertyPopulation:是否需要继续给属性注入值
- mbd.isSynthetic(): 返回bean definition 是否是合成的,(合成:即不是应用程序本身定义的)
- hasInstantiationAwareBeanPostProcessors():返回该工厂是否持有实例化的WareBeanPostProcessor,该实例化将在关闭时应用于单例bean。
- 当这个bean不是合成的,且它持有实例化的WareBeanPostProcessor ,则获取所有的BeanPostProcessor,判断当它是InstantiationAwareBeanPostProcessors 类型时,通过调用postProcessAfterInstantiation方法,可以在属性注入前,最后一次修改bean的值,如果调用返回false,表示不必继续进行依赖注入,直接返回
- postProcessAfterInstantiation :如果我们需要在这一步修改,则可以重写这个方法,目前默认方法体,直接返回true
2.3 选择合适的注入模式
-
判断当前bean 有无定义的属性值,如果有就返回当前bean 所有的属性值,否则返回null
- mbd.getPropertyValues():
- 这里我们可以看到pvs是一个MutablePropertyValues实例,里面实现了PropertyValues接口,主要作用是:提供属性的读写操作实现,同时可以通过调用构造函数实现深拷贝
- mbd.getPropertyValues():
-
mbd.getResolvedAutowireMode():获取注入方式。
- AUTOWIRE_NO = 0(默认):常量,指示没有外部定义的自动注入
- AUTOWIRE_BY_NAME = 1:常量,指示按名称自动装配bean属性
- AUTOWIRE_BY_TYPE = 2:常量,指示按类型自动装配bean属性
- AUTOWIRE_CONSTRUCTOR = 3:常量,指示自动关联最贪婪的构造函数
- AUTOWIRE_AUTODETECT = 4:常数,表示通过bean类的自省来确定适当的自动装配策略
-
所以这个方法,先判断它需不需要自省,不需要直接返回它本身,需要的话根据构造函数的参数数量来判断,参数数量为0 返回 AUTOWIRE_BY_TYPE,否则 返回 AUTOWIRE_CONSTRUCTOR
-
通过前面获取的 resolvedAutowired,来选择合适的注入方式
-
autowireByName :通过名称自动装配,详解见 2.3.1
-
autowireByType : 通过类型自动装配,详解见 2.3.2
-
把注入后的 newPvs 重新赋给 pvs
1. autowireByName(beanName, mbd, bw, newPvs)
- propertyNames :首先获取所有需要进行依赖注入的属性名称,然后保存起来。详解见 2.3.3
- 遍历 propertyNames ,判断容器中是否含有该 属性的bean,注意:这里含有bean 或 bean 的定义都算。详解见2.3.4
- 如果包含的话,先从容器中获取到这个bean,则把它 name -> bean 加入到 pvs 中去
- 最后把它注册到当前bean 的 dependentBeanMap(保存当前bean 依赖的bean 的名称集合)中去
2. autowireByType(beanName, mbd, bw, newPvs);
- 获取类型转换器,如果没有,就直接使用 bw ,BeanWrapper详解
- autowiredBeanNames : 保存以来的bean 的名称的 Set 集合。
- propertyNames :首先获取所有需要进行依赖注入的属性名称,然后保存起来。详解见 2.3.3
- 遍历 propertyNames ,
- getPropertyDescriptor(propertyName):获取被包装对象的特定属性的属性描述符
- 如果属性是 Object 类型的 则不进行 装配
- 获取属性的写方法相关参数
- 判断它有没有实现,PriorityOrdered.class 接口
- 封装一个 依赖描述的对象,AutowireByTypeDependencyDescriptor(记录了依赖对象的基本信息,源码挺简单的,就是设置一些属性,大家可以自己看看)
- resolveDependency(desc, beanName, autowiredBeanNames, converter):这里会根据传入desc里的入参类型,作为依赖装配的类型,再根据这个类型在BeanFacoty中查找所有类或其父类相同的BeanName,最后根据BeanName获取或初始化相应的类,然后将所有满足条件的BeanName填充到 autowiredBeanNames 中。这个方法后续有时间的话,会详解
- 当 autowired 不为null 的时候,把它添加到 pvs 中去
- 遍历 autowiredBeanNames 最后把它注册到当前bean 的 dependentBeanMap(保存当前bean 依赖的bean 的名称集合)中去
3. unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw)
- 属性的写方法不为null && 该属性需要进行依赖检查的 && bean Definition 中没有包含的 && 不是简单属性,或数据元素是简单属性的数组,符合上面条件的元素,把他们的属性名返回
- 简单属性:
4. containsBean(String name)
- 先判断当前容器中有无,该name 处理后的beanName 的 bean 或者 beanDefinition 信息,如果有则继续判断当它不是BeanFactory (即 name不为null 且 name 不以 '&' 开头)或者它是一个 FactoryBean 则返回true,算包含。
- 当本容器不包含的时候,会尝试获取它的 父容器,接着判断,直至父容器为 null
2.4 属性值的填充和依赖检查
- hasInstAwareBpps : 是否持有实例化 InstantiationAwareBeanPostProcessor 的bean
- needsDepCheck : 是否需要类型检查(setter 方法上使用@Required ,用来检查指定属性,是否被赋值)
- filteredPds : 保存属性描述符的数组
- 当 hasInstAwareBpps 为 true
- 遍历当前bean 所有的 BeanPostProcessor ,当它是 InstantiationAwareBeanPostProcessor 类型时,执行 postProcessProperties 这个方法。
- postProcessProperties:在工厂将给定的属性值应用到给定的bean之前对它们进行后处理,不需要任何属性描述符。如:@Resource , @Autowired, @Value ,@Inject 等注解 进行值注入。AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor 等均实现了。
- 当pvsToUse == null 的时候,调用 filterPropertyDescriptorsForDependencyCheck,对bw 的属性进行过滤注册(cglib 代理的属性 || 指定需要过滤的类型 || 需要忽略的接口类型),详解见 2.4.1
- 执行当前 InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues (这里大多实现类这个方法已废弃,应该是对以前低版本的兼容)
- postProcessPropertyValues:作用和 postProcessProperties 差不多,已废弃
- 当需要依赖检查时进入,
- 当 filteredPds 仍为 null ,调用 filterPropertyDescriptorsForDependencyCheck 对bw 的属性进行过滤注册,详解见 2.4.1
- 进行依赖检查,详解见 2.4.4
1.filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache)
- filteredPropertyDescriptorsCache :已筛选PropertyDescriptor的缓存:bean类到PropertyDescriptor数组
- 先通过 bean 类从 filteredPropertyDescriptorsCache 中取出 PropertyDescriptor 数组
- 当 filtered == null 时,进入
- filterPropertyDescriptorsForDependencyCheck(bw):从给定的BeanWrapper中提取一组经过过滤的propertydescriptor,不包括被忽略的依赖类型或被忽略的属性,详解见 2.4.2
- cache == true时,且 filteredPropertyDescriptorsCache 中取出的 filtered不为null,则把过滤后的属性数组,再放到 filteredPropertyDescriptorsCache 中去
- 返回 filtered
2. filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw)
- 从bw 中取出所有的 PropertyDescriptor,然后调用 isExcludedFromDependencyCheck(2.4.3 详解) 这个方法 进行过滤
3. isExcludedFromDependencyCheck(PropertyDescriptor pd)
这里其实就是过滤 cglib 代理的属性 || 指定需要过滤的类型 || 需要忽略的接口类型
4. checkDependencies(beanName, mbd, filteredPds, pvs);
- 获取mbd 的依赖检查类型
- DEPENDENCY_CHECK_NONE = 0 :常量,表示根本没有依赖项检查
- DEPENDENCY_CHECK_OBJECTS = 1:常量,表示对象引用的依赖性检查。
- DEPENDENCY_CHECK_SIMPLE = 2: 常量,指示对“简单”属性进行依赖性检查。
- DEPENDENCY_CHECK_ALL = 3: 常量,指示对所有属性进行依赖性检查
- 当它写方法不为null && (pvs == null || pvs 不包含当前 属性名)
- isSimple : 记录当前这个这个属性是不是简单属性
- 当 unsatisfied ==true 时,抛出异常
2.5 最终处理
applyPropertyValues :把当前属性填充给这个bean,因为这个方法比较长,今天就先到这 ,下次我在详细讲讲。