Spring源码学习第十一天==>填充Bean属性

前言:Bean的创建所经历的步骤大致为实例化,填充属性,初始化。之前在Spring第九天的时候描述过实例化的过程了,所以这篇文章来描述Bean的填充属性环节

入口方法:AbstractAutowireCapableBeanFactory类的populateBean(beanName, mbd, instanceWrapper)方法。

1.首先属性的类型可以分为大致这么几类

  • 8种基本数据类型
  • 引用类型
  • 集合类型,集合类型的元素可以为基本数据类型与引用类型

2.属性注入的方式,根据Spring源码可以得出有5种,在AutowireCapableBeanFactory类中可以查看

  • AUTOWIRE_NO=0:默认,表示不选择自动装配
  • AUTOWIRE_BY_NAME=1:表示按名称进行自动注入
  • AUTOWIRE_BY_TYPE=2:表示按类型进行自动注入
  • AUTOWIRE_CONSTRUCTOR=3:按构造器进行注入
  • AUTOWIRE_AUTODETECT=4:自动选择 

3.填充属性详细介绍

  •      实例化对象为空,但是BeanDefinition中却有属性键值对信息,就抛出异常
if (bw == null) {
			// 如果mbd有需要设置的属性
			if (mbd.hasPropertyValues()) {
				// 抛出bean创建异常
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				// 没有可填充的属性,直接跳过
				return;
			}
}
  • 容器中是否存在InstantiationAwareBeanPostProcessor及其子类,该类是用于丰富Bean信息的类,可以在Bean的实例化前后,初始化前后,及其属性设置上进行操作,如果存在这种类型的后置处理器,就调用他们的实例化后要执行的丰富postProcessAfterInstantiation()
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			//遍历工厂中的BeanPostProcessor对象
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//如果 bp 是 InstantiationAwareBeanPostProcessor 实例
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// postProcessAfterInstantiation:一般用于设置属性
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
}
  • 判断xml文件中定义Bean信息的时候是否有显示的设置<property/>,如果有的话就保存在PropertyValues对象中
//PropertyValues:包含以一个或多个PropertyValue对象的容器,通常包括针对特定目标Bean的一次更新
//如果mdb有PropertyValues就获取其PropertyValues
// xml配置文件中的<property/>获取到该标签的键值对
 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
  • 根据注入方式选择对应的方法去获取键值对的信息,主要是根据名称注入与类型注入两种方式,文章最后会附上一张流程图,会给出autowiredByName方式的处理流程
// 获取 mbd 的 自动装配模式
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// 如果 自动装配模式 为 按名称自动装配bean属性 或者 按类型自动装配bean属性
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			//MutablePropertyValues:PropertyValues接口的默认实现。允许对属性进行简单操作,并提供构造函数来支持从映射 进行深度复制和构造
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			// 根据autotowire的名称(如适用)添加属性值
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				//通过bw的PropertyDescriptor属性名,查找出对应的Bean对象,将其添加到newPvs中
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			// 根据自动装配的类型(如果适用)添加属性值
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				//通过bw的PropertyDescriptor属性类型,查找出对应的Bean对象,将其添加到newPvs中
				autowireByType(beanName, mbd, bw, newPvs);
			}
			//让pvs重新引用newPvs,newPvs此时已经包含了pvs的属性值以及通过AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE自动装配所得到的属性值
			pvs = newPvs;
		}
  • 调用InstantiationAwareBeanPostProcessor及其子类的postProcessPropertyValues()方法,以针对属性进行一些操作
//@autoWired注解的注入工作
		if (hasInstAwareBpps) {
			//如果pvs为null
			if (pvs == null) {
				//尝试获取mbd的PropertyValues
				pvs = mbd.getPropertyValues();
			}
			//遍历工厂内的所有后置处理器
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//如果 bp 是 InstantiationAwareBeanPostProcessor 的实例
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					//将bp 强转成 InstantiationAwareBeanPostProcessor 对象
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//postProcessProperties:在工厂将给定的属性值应用到给定Bean之前,对它们进行后处理,不需要任何属性扫描符。该回调方法在未来的版本会被删掉。
					// -- 取而代之的是 postProcessPropertyValues 回调方法。
					// 让ibp对pvs增加对bw的Bean对象的propertyValue,或编辑pvs的proertyValue
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					//如果pvs为null
					if (pvsToUse == null) {
						//如果filteredPds为null
						if (filteredPds == null) {
							//mbd.allowCaching:是否允许缓存,默认时允许的。缓存除了可以提高效率以外,还可以保证在并发的情况下,返回的PropertyDesciptor[]永远都是同一份
							//从bw提取一组经过筛选的PropertyDesciptor,排除忽略的依赖项或忽略项上的定义的属性
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						//postProcessPropertyValues:一般进行检查是否所有依赖项都满足,例如基于"Require"注释在 bean属性 setter,
						// 	-- 替换要应用的属性值,通常是通过基于原始的PropertyValues创建一个新的MutablePropertyValue实例, 添加或删除特定的值
						// 	-- 返回的PropertyValues 将应用于bw包装的bean实例 的实际属性值(添加PropertyValues实例到pvs 或者 设置为null以跳过属性填充)
						//回到ipd的postProcessPropertyValues方法
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						//如果pvsToUse为null,将终止该方法精致,以跳过属性填充
						if (pvsToUse == null) {
							return;
						}
					}
					//让pvs引用pvsToUse
					pvs = pvsToUse;
				}
			}
		}

要注意的是,以上步骤,除了InstantiationAwareBeanPostProcessor及其子类的内部实现逻辑我们不得而知。其他的方式都没有进行属性的赋值,只是寻找需要注入的属性,并将属性和值保存到PropertyValues对象中。

  • 最后将PropertyValues中的键值对进行属性注入操作
//如果pvs不为null
		if (pvs != null) {
			//应用给定的属性值,解决任何在这个bean工厂运行时其他bean的引用。必须使用深拷贝,所以我们 不会永久地修改这个属性
			applyPropertyValues(beanName, mbd, bw, pvs);
		}

最后,附上流程图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值