好玩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;
}

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章