spring 源码系列(八)bean的属性装配populateBean()

1 先贴出源码

源码及注释来自【Spring源码阅读】populateBean实现 依赖注入源码解析

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // pvs是一个MutablePropertyValues实例,里面实现了PropertyValues接口,提供属性的读写操作实现,同时可以通过调用构造函数实现深拷贝
    // 在本例中,里面存在一个propertyValueList,里面只有一个propertyValue:key->value="student"->RuntimeBeanReference("<student>")
	PropertyValues pvs = mbd.getPropertyValues();

	if (bw == null) {
		if (!pvs.isEmpty()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// 空对象直接返回
			return;
		}
	}

	// 给InstantiationAwareBeanPostProcessors最后一次机会在属性注入前修改Bean的属性值
	// 具体通过调用postProcessAfterInstantiation方法,如果调用返回false,表示不必继续进行依赖注入,直接返回
	boolean continueWithPropertyPopulation = true;

	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					continueWithPropertyPopulation = false;
					break;
				}
			}
		}
	}

	if (!continueWithPropertyPopulation) {
		return;
	}

    // 根据Bean配置的依赖注入方式完成注入,默认是0,即不走以下逻辑,所有的依赖注入都需要在xml文件中有显式的配置
    // 如果设置了相关的依赖装配方式,会遍历Bean中的属性,根据类型或名称来完成相应注入,无需额外配置
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		// 深拷贝当前已有的配置
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根据名称进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// // 根据类型进行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
        // 结合注入后的配置,覆盖当前配置
		pvs = newPvs;
	}
    
    // 容器是否注册了InstantiationAwareBeanPostProcessor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 是否进行依赖检查
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
	if (hasInstAwareBpps || needsDepCheck) {
	    // 过滤出所有需要进行依赖检查的属性编辑器
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
			    // 如果有相关的后置处理器,进行后置处理
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
		if (needsDepCheck) {
		    // 检查是否满足相关依赖关系,对应的depends-on属性,需要确保所有依赖的Bean先完成初始化
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
	}
    // 将pvs上所有的属性填充到BeanWrapper对应的Bean实例中,注意到这一步,TestBean的student属性还是RuntimeBeanReference,即还未解析实际的Student实例
	applyPropertyValues(beanName, mbd, bw, pvs);
}

2 流程图

在这里插入图片描述

3 具体调试实例

3.1 实例1:使用@AutoWired

3.1.1 java bean代码

@Component
@PropertySource("classpath:db.properties")
public class AutoWiredBean {
    @Autowired
    private MessageService messageService;

    @Value("${db.driver}")
    private String driverClass;

}

public interface MessageService {
    String getMessage();
}

@Service
public class MessageServiceImpl implements MessageService {

    public String getMessage() {
        return "hello world";
    }
}

3.1.2 调试结果

  1. 既不走autowireByName,也不走autowireByType。
  2. 会调用AnnotationConfigApplicationContext的postProcessPropertyValues(),其具体功能及原理详见我的另一篇博客:spring 源码系列(六)- 处理@AutoWired和@Value的后置处理器AutowiredAnnotationBeanPostProcessor
  3. 虽然会创建一个pvs,但是length一直为0,即使走了postProcessPropertyValues(),pvs也一直是空着的,所以最后一步applyPropertyValues()什么都没干。

3.2 普通java bean

3.2.1 java bean代码

public class Person {
    private String name;

    public Person() {
    }

    public Person(String name){
        this.name=name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }
}

@Component
public class TestBean {
    private Person person;

    public void echo() {
        System.out.println("I'm a student : " + person);
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

3.2.2 调试结果

反复测试确认,使用普通bean的话,啥都没干。

3 总结

populateBean()方法虽然看上去比较复杂,但无论是AutoWireByType还是AutoWireByName都没有调用,同时从目前的测试来看:applyPropertyValues()好像也没调用。实际上就只是调用了属于InstantiationAwareBeanPostProcessor系列的Bean后置处理器的postProcessPropertyValues()方法。 尤其是AutowiredAnnotationBeanPostProcessor这个类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值