spring 提供了四种依赖注入的方式:
- setter注入
- 构造器注入
- 字段注入
- 方法注入
在项目中,我们使用的最多的就是基于@Autowired的字段注入,下面我们基于非延时加载的单例的spring bean结合源码分析以下spring 是如何实现基于@Autowired的字段注入的。
源码阅读
@Autowire 的处理流程包含在spring bean的创建流程中,因此我们的源码阅读从AbstractAutowireCapableBeanFactory.doCreateBean()开始。
源码一:AbstractAutowireCapableBeanFactory.doCreateBean()
该方法是spring 根据 beanDefinition 创建spring bean的核心代码,该方法返回的就是spring bean对象
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 返回spring bean实例,如果没有指定构造器或者工厂方法,通常就是简单的通过无参构造器返回一个对象。注意这时候返回的对象,所有的字段都还是默认值
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 省略部分代码
// spring 用于解决循环依赖的缓存,不在本篇文章的讨论范围,下篇文章再讨论
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 会在这一步调用AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,处理@Autowire、@value等注入,详情见源码2
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 省略部分代码
return exposedObject;
}
源码二:AutowiredAnnotationBeanPostProcessor.postProcessProperties()
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 获取标注了@Autowired、@Value 或者@Inject 主键的字段 封装为InjectionMetadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 处理@Autowired的注入,详情见源码3
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
源码三:InjectionMetadata.inject()
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历需要插入字段(注意InjectedElement不仅仅代表字段,也可以代表构造器,方法等),然后调用InjectedElement.inject()方法
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// 调用InjectedElement.inject()方法, 详情见源码4;
element.inject(target, beanName, pvs);
}
}
}
源码四:AutowiredFieldElement.inject()
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 根据类型在ioc容器中查找对应的spring bean。如果依赖的的spring bean 还没有创建,就会先初始化对应的bean。
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
// 省略部分代码
if (value != null) {
ReflectionUtils.makeAccessible(field);
// 将对应的spring bean 设置到字段中
field.set(bean, value);
}
}
注1:注意这里的InjectedElement 是 AutowiredAnnotationBeanPostProcessor 内部的InjectedElement 而不是InjectionMetadata的内部的InjectedElement 。
总结
限于篇幅,本文只是简单的阐述了@Autowired在源码中的主要流程,忽略了源码中很多细节,例如:源码4中DefaultListableBeanFactory.resolveDependency()中是如何处理单个对象的注入,集合对象的注入等等。这些都还需要翻看源码,细细阅读。事实上上述流程同样适用于@Value 注解的注入,只是在DefaultListableBeanFactory.resolveDependency() 中有些区别。