Spring源码阅读--@Autowired注解自动装配

原创
2017/05/27 16:25
阅读数 1.5K

@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方法的实现:

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

@Override
public 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类型的其实就是给方法参数自动注入并调用方法。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
2 收藏
分享
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部