博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码阅读--@Autowired注解自动装配
阅读量:5909 次
发布时间:2019-06-19

本文共 4084 字,大约阅读时间需要 13 分钟。

hot3.png

@Autowired注解对应的处理器是 AutowiredAnnotationBeanPostProcessor(太长, 后面简称AABPP),这个从注解的注释上可以获悉。

它上层接口是:MergedBeanDefinitionPostProcessor, 父类是InstantiationAwareBeanPostProcessor, 分别看它们的方法参数就知道他们的主要干预的对象,前者干预BeanDefinition,后者干预bean。

根据这两个接口方法反推到被调用的地方,然后看是怎么触发AABPP里面的方法的,如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory		implements AutowireCapableBeanFactory {	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {		//创建对象		// Allow post-processors to modify the merged bean definition.		synchronized (mbd.postProcessingLock) {			if (!mbd.postProcessed) {				//这个里面是第一次触发AABPP的方法				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);				mbd.postProcessed = true;			}		}		//...		// Initialize the bean instance.		Object exposedObject = bean;		try {			//填充对象   这个里面解析了依赖的bean,@Autowired的自动注入就是这里面解析的			populateBean(beanName, mbd, instanceWrapper);			if (exposedObject != null) {				//初始化方法				exposedObject = initializeBean(beanName, exposedObject, mbd);			}		} catch (Throwable ex) {			//...		}		//...		return exposedObject;	}}

一、看applyMergedBeanDefinitionPostProcessors方法的实现:

155914_PPnz_1445156.png

这里就是调用了postProcessMergedBeanDefinition方法,看AABPP里面该方法的实现:

@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
beanType, String beanName) { if (beanType != null) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }}private InjectionMetadata findAutowiringMetadata(String beanName, Class
clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility // with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); // 单例式的写法, 保证全局只被执行一次 if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } //这里是根据class取出带有@Autowired的元数据 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata;}

到这里定位到了具体解析@Autowired的方法了buildAutowiringMetadata,这个里面就是根据class通过反射获取到Field或Method,判断有没有被@Autowired标识,构造到InjectionMetadata返回。

二、看populateBean方法里面是怎么触发AABPP的:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {	//...	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;					}				}			}		}		//...	}	//...}

主要还是看AABPP里面postProcessPropertyValues方法是怎么处理的:

public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,		String beanName) throws BeansException {	//这个在上一步已经获取并缓存到map中了	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);	try {		//这一步是具体的注入了		metadata.inject(bean, beanName, pvs);	} catch (Throwable ex) {		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);	}	return pvs;}

InjectionMetadata里面有一些待注入的元素InjectedElement,遍历元素调用inject方法,这里InjectedElement分为Field和Method两种子类实现两种逻辑:Field类型的是通过bean工厂获取到依赖的对象然后反射设置value值;Method类型的其实就是给方法参数自动注入并调用方法。

转载于:https://my.oschina.net/chengxiaoyuan/blog/910370

你可能感兴趣的文章