Spring中Bean实例化过程中的populateBean方法

关联博文
Spring后置处理器中的InstantiationAwareBeanPostProcessor详解
Spring中Bean实例化过程中的initializeBean方法
Spring中Bean实例化过程中的populateBean方法
Spring中@Autowired与@Resource自动注入实现原理

这是bean实例化后非常重要的一个环节。用bean定义中的属性值填充给定BeanWrapper中的bean实例,也就是属性赋值过程。这里会涉及到成员的依赖注入解析过程,也会涉及到循环依赖。

本文环境:SpringBoot+mybatisplus。

如下所示,在populateBean(beanName, mbd, instanceWrapper);方法执行前我们的fileController实例:

// 如下是我们定义的成员
private static  final Logger logger= LoggerFactory.getLogger(FileController.class);

@Autowired
private SysFileService fileService;

@Value("${com.jane.file.baseFilePath}")
private String baseFilePath;

@Value("${com.jane.configjson.baseFilePath}")
private String configJsonPath;

@Autowired
private SysFileMapper fileMapper;

private static  String name="jane";
private   String sex="男";

在这里插入图片描述
接下来我们跟踪分析一下populateBean方法。


【1】方法概览

我们来看一下AbstractAutowireCapableBeanFactory的populateBean方法。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// BeanWrapperImpl内部包含了目标Bean实例 、conversionService
	if (bw == null) {
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		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.
//在bean 属性被设置前给InstantiationAwareBeanPostProcessors 计划修改bean state
// Synthetic默认为false
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
	}

// 从mbd中获取属性值键值对
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

// 判断autoWire类型,进而解析依赖。如果该值为0  则不会执行if逻辑
// 当然你可以选择对autowire进行设置
	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
			// 根据Name注入
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		// 根据TYPE注入
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}

// 容器中是否有InstantiationAwareBeanPostProcessor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

// 是否需要进行依赖检测
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		// 调用InstantiationAwareBeanPostProcessor 的postProcessProperties方法
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

//这里很重要,会触发AutowiredAnnotationBeanPostProcessor实现依赖的解析
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
	}
	// 如果需要依赖检测,进行依赖检测
	if (needsDepCheck) {
		if (filteredPds == null) {
			filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		}
		// 进行依赖检查
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}

// 如果pvs不为null,进行赋值
	if (pvs != null) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

如上代码所示,核心逻辑可以梳理为如下几个步骤:

  • ① 调用InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation
  • ② 从mbd获取pvs
  • ③ 判断AutowireMode,如果是AUTOWIRE_BY_NAME或者AUTOWIRE_BY_TYPE触发依赖解析;
  • ④ 获取hasInstAwareBpps与needsDepCheck标识;前者判断是否有InstantiationAwareBeanPostProcessor,后者判断是否需要进行依赖检查。
  • ⑥ 如果hasInstAwareBpps为true,则给InstantiationAwareBeanPostProcessor一个机会触发其postProcessProperties(或者postProcessPropertyValues)更新pvs的值。这一步很关键哦,如果resolvedAutowireMode为0,那么我们@Autowired注解的依赖解析就发生在这里。
  • ⑦ 如果④中获取的needsDepCheck标识为true,则进行依赖检查(checkDependencies);
  • ⑧ 如果pvs不为null,则尝试给bean赋值。

【2】方法分析

这里调用InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation我们不用过于关注,默认实现为true,只在自定义字段注入的时候才需要重写该方法。

如果resolvedAutowireModeAUTOWIRE_BY_NAME或者AUTOWIRE_BY_TYPE那么就会触发根据名称或者根据类型的依赖解析,本文这里我们不打算进一步分析其细节会在另外博文里面说明。

我们需要关注的是InstantiationAwareBeanPostProcessorpostProcessPropertiespostProcessPropertyValues方法。这两个方法十分重要,尤其是前者。如CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor就是在postProcessProperties方法中处理@Resource与@Autowire的注解,实现依赖解析与注入的。依赖解析的过程也就是getBean的过程,那么这个过程又会涉及到循环依赖。

// 依赖解析的调用栈
doGetBean:245, AbstractBeanFactory 
getBean:202, AbstractBeanFactory 
resolveCandidate:276, DependencyDescriptor 
doResolveDependency:1287, DefaultListableBeanFactory 
resolveDependency:1207, DefaultListableBeanFactory 
inject:640, AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement 
inject:116, InjectionMetadata 
postProcessProperties:399, AutowiredAnnotationBeanPostProcessor 
populateBean:1422, AbstractAutowireCapableBeanFactory 

而postProcessPropertyValues则是一种补偿手段,不过CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessorInstantiationAwareBeanPostProcessorAdapter均为该方法贴上了“过期”的标识,标明该方法在未来版本将会放弃。

另外,ConfigurationClassPostProcessor.ImportAwareBeanPostProcessorpostProcessProperties方法会为bean设置beanFactory(DefaultListableBeanFactory)。


依赖检查

如下所示基本原则是判断pvs中是否包括pds的属性name,如果不包括那么再进行进一步判断,不满足将会抛出异常。

在这里插入图片描述
也就是说,在spring IOC容器中,设计了一个依赖检查特性,通过它spring可以帮助应用检查是否所有的属性都已经被正确设置。在具体使用的时候,应用只需要在Bean定义中设置dependency-check属性来指定依赖检查模式接口。如下所示,这里可以将属性设置为none、simple、object、all四种模式,默认的模式是none

//no dependency check at all.
public static final int DEPENDENCY_CHECK_NONE = 0;

// dependency checking for object references.
public static final int DEPENDENCY_CHECK_OBJECTS = 1;

// dependency checking for "simple" properties.
public static final int DEPENDENCY_CHECK_SIMPLE = 2;

//dependency checking for all properties
public static final int DEPENDENCY_CHECK_ALL = 3;

applyPropertyValues

这个方法就是将前面得到的PropertyValues设置给BeanWrapper,也就是属性赋值的过程。这里会涉及到运行时引用的解析并对list/map/set等集合类型进行处理。

如下所示,最开始得到的PropertyValues pvs为null,默认情况下resolvedAutowireMode为0也不需要进行依赖检查。

在这里插入图片描述

InstantiationAwareBeanPostProcessorpostProcessProperties执行完后,那么其所依赖的比如fileSevice、baseFilePath、configJsonPath、fileMapper等均已完成赋值。

在这里插入图片描述

本文环境下,为controller实例化,pvs为空。那么pvs什么情况不为空呢?比如为我们的xxxMapper实例化的时候,其将会解析sqlSessionFactory、sqlSessionTemplate放到pvs中。

0 = {PropertyValue@9394} "bean property 'addToConfig'"
1 = {PropertyValue@9395} "bean property 'sqlSessionFactory'"
2 = {PropertyValue@9396} "bean property 'sqlSessionTemplate'"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值