好玩Spring之@Resource的工作原理

在上一篇,我们介绍了@Autowired的工作原理,本篇我们依然借用上一篇的例子,来说明@Resource的工作原理

@Component
public class Controller {
 
	@Resource
	public Service service;
 
	public void add() {
		service.add();
	}
}

在例子中,我们只是把@Autowired换成了@Resource,其他都没变,执行的结果都是一样的,那@Resource是怎么被注入的呢?

基本的流程,跟@Autowired是大致相同的。

1. 获取@Resource数据

如果看过@Autowired的分析,@Resource就会非常容易理解,在@Autowired的讲解中,我们提到当执行到AbstractAutowireCapableBeanFactory的doCreateBean方法,会有这面一段代码

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
	if (!mbd.postProcessed) {
		try {
			// @Autowired注解在这里注入,@Resource也在这里注入
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Post-processing of merged bean definition failed", ex);
		}
		mbd.postProcessed = true;
	}
}

这里允许后置处理来修改bean definition,@AutoWired、@Resource就是后置处理器中的一员,进入applyMergedBeanDefinitionPostProcessors方法,


protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    // 当bp为CommonAnnotationBeanPostProcessor时,会进行@Resource的注入
	// 当bp为AutowiredAnnotationBeanPostProcessor时,会进行@Autowired的注入
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof MergedBeanDefinitionPostProcessor) {
			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}
}

当bp为CommonAnnotationBeanPostProcessor时,执行CommonAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition方法,

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	// 查找被@Resource注解的属性和方法
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

从这个方法开始,@Resource的获取metadata数据的流程,跟@Autowired差不多就一样了。

2. 注入Resource数据

当程序执行到AbstractAutowireCapableBeanFactory的populateBean方法时,有如下代码

for (BeanPostProcessor bp : getBeanPostProcessors()) {
	if (bp instanceof InstantiationAwareBeanPostProcessor) {
		InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
		PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
		if (pvsToUse == null) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			// 生命周期 step5 InstantiationAwareBeanPostProcessor.postProcessPropertyValues
			pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				return;
			}
		}
		pvs = pvsToUse;
	}
}

当beanName为controller时,会进入postProcessProperties方法。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
	try {
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
	}
	return pvs;
}

进行了真正的反射注入操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值