@Autowired常用的就是属性注入和构造方法注入

大体的逻辑是这样的

  • 通过反射查找bean的class下所有注解了@Autowired的字段和方法
  • 获取到字段,通过getBean(字段)获取到对应bean,然后再通过反射调用field的set将bean注入

@Autowired源码分析

AutowiredAnnotationBeanPostProcessor

该类是@Autowired的具体实现类,先预览一下方法

发现实际有机会介入bean的创建操作只有可能是后置处理器,用于后置处理的有3个方法,其中一个过时不用,分别是postProcessMergedBeanDefinitionpostProcessProperties后置处理,我们看一下这两个方法的具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 1. 寻找bean中所有被@Autowired注释的属性,并将属性封装成InjectedElement类型
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}


@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 1. 寻找通过@Autowired注解的属性或者方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 2. 注入
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;
}

首先找出所有注解了@Autowired的属性或者方法,然后进行注入,当然postProcessMergedBeanDefinition后置处理器的调用肯定是在postProcessProperties之前的,我们先回顾一下bean的创建流程

1.查找所有@Autowired

1
2
// 寻找bean中所有被@Autowired注释的属性,并将属性封装成InjectedElement类型
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// 获取缓存的key值,一般以beanName做key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 从缓存中获取metadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// 检测metadata是否需要更新
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 通过clazz类,查找所有@Autowired的属性或者方法,并封装成InjectionMetadata类型
metadata = buildAutowiringMetadata(clazz);
// 将metadata加入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}

可以看到spring依然在用缓存的方式提高性能,buildAutowiringMetadata(clazz)里主要查找所有@Autowired,具体流程:

  • 外层do...while...的村换被用于诋毁查找父类的@Autowired属性或方法
  • 通过反射的方式获取到所有属性并循环验证每一个属性是否被@Autowired注解
  • 将查找到包含Autowired注解的filed封装成AutowiredFieldElement,加入到列表中
  • 循环在查找方法上的注解
  • 将找到的方法封装成AutowiredMethodElement,并加入列表
  • 将找到的左右元素列表和clazz作为参数生成metadata数据返回

2.注入

1
2
// 注入
metadata.inject(bean, beanName, pvs);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
// 循环注入,这里有可能是AutowiredFieldElement也可能AutowiredMethodElement,因此调用的inject是2个不同的方法
element.inject(target, beanName, pvs);
}
}
}

利用for循环,遍历刚刚我们查到的elements列表,进行注入。

这里的element有可能是AutowiredFieldElement类型、或AutowiredMethodElement类型。各自代表@Autowired注解在属性上、以及注解在方法上的两种不同元素

核心语句还是这2句

1
2
3
// 反射调用注入方法,将获取到的所有bean作为参数
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);