Autowired注解依赖注入原理

Spring 提供了 @Autowired 注解,可用于自动注入所需的 bean,与 xml 配置相比更加简洁,本文主要关注 @Autowired 注解的实现原理。

Autowired 注解用法

Autowired 注解的定义如下:

1
2
3
4
5
6
7
8
9
10
11
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}

它可用于构造函数、普通方法、参数、field 等,包含一个 required 属性,默认值为 true。

使用示例

定义一个 BusinessService 接口,它的实现类为 BusinessServiceImpl,在 BusinessServiceImpl 上添加 @Service 注解,表明这是一个 Service 类型的 bean。

1
2
3
4
5
6
7
8
9
10
public interface BusinessService {
void doBusiness();
}

@Service
public class BusinessServiceImpl {
public void doBusiness() {
// 省略实现
}
}

使用时只需要在目标 bean 的 BusinessService 属性上加上 @Autowired 注解即可,Spring 会自动完成依赖 bean 的注入。

1
2
3
4
5
6
7
8
9
10
11
@Component
public class Test {
@Autowired
private BusinessService businessService;

public void doSomething() {
// 这里可以直接使用
businessService.doBusiness();
}
// 省略其他代码
}

Autowired 实现原理

Autowired 注解的依赖注入是通过 AutowiredAnnotationBeanPostProcessor 来实现的。

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 类的继承结构如下图所示:

image-20200407011625401

它实现了多个接口,这里主要关注如下两个接口:

  • MergedBeanDefinitionPostProcessor 接口。提供了一个 postProcessMergedBeanDefinition 回调方法,可用于处理 MergedBeanDefinition。

    1
    2
    3
    4
    5
    6
    7
    /**
    * Post-process the given merged bean definition for the specified bean.
    * @param beanDefinition the merged bean definition for the bean
    * @param beanType the actual type of the managed bean instance
    * @param beanName the name of the bean
    */
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
  • InstantiationAwareBeanPostProcessor 接口。提供了一个 postProcessProperties 回调方法,可用于在 PropertyValues 应用之前对其进行处理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /**
    * Post-process the given property values before the factory applies them
    * to the given bean, without any need for property descriptors.
    * <p>Implementations should return {@code null} (the default) if they provide a custom
    * {@link #postProcessPropertyValues} implementation, and {@code pvs} otherwise.
    * In a future version of this interface (with {@link #postProcessPropertyValues} removed),
    * the default implementation will return the given {@code pvs} as-is directly.
    * @param pvs the property values that the factory is about to apply (never {@code null})
    * @param bean the bean instance created, but whose properties have not yet been set
    * @param beanName the name of the bean
    * @return the actual property values to apply to the given bean (can be the passed-in
    * PropertyValues instance), or {@code null} which proceeds with the existing properties
    * but specifically continues with a call to {@link #postProcessPropertyValues}
    * (requiring initialized {@code PropertyDescriptor}s for the current bean class)
    * @throws org.springframework.beans.BeansException in case of errors
    * @since 5.1
    * @see #postProcessPropertyValues
    */
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    return null;
    }

通过下图可以了解它们处于 bean 创建的哪个阶段:

image-20200402015737100

AutowiredAnnotationBeanPostProcessor 就是通过 bean 创建过程中的这两个扩展点完成 @Autowired 依赖注入的

  1. 获取 class 上的依赖注入注解信息,构建依赖注入元数据,添加到缓存中
  2. 查询依赖注入元数据,调用其 inject 方法,从 beanFactory 中获取依赖的 bean,通过反射设置 bean 完成依赖注入
image-20200409004319360

获取依赖注入元数据

AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 接口,通过 postProcessMergedBeanDefinition 回调方法完成依赖注入元数据的查找和缓存工作。

1
2
3
4
5
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// annotation 依赖注入:查找 bean 上配置的依赖注入注解配置,并缓存起来
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}

构建出来的依赖注入元数据可能要使用多次,因此 findAutowiringMetadata 方法在第一次构建好数据之后会将其缓存起来,保存到 AutowiredAnnotationBeanPostProcessor 的缓存中,这个缓存的定义如下:

1
2
3
4
5
6
/**
* 依赖注入的解析缓存
* key: beanName 或者 class name
* value: 解析出来的依赖注入配置
*/
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);

使用时先从缓存查询,若查不到则进行构建,然后添加到缓存中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable 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);
}
// 构建 autowire 的元数据,包括 field 和 method
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}

构建依赖注入元数据

@Autowired 注解可以应用到属性(field)上,也可以应用到方法(method)上,因此相应的元数据也包括这两种。

field 的处理

遍历目标类的属性(field),查找上面的依赖注入注解,找到后读取注解的 required 值,然后构建 AutowiredFieldElement 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 查找字段上的 autowire 注解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);

// 构建 autowire 元数据
currElements.add(new AutowiredFieldElement(field, required));
}
});

method 的处理

遍历模板类的方法(method),查找上面的依赖注入注解,找到后读取注解的 required 值、获取方法的 PropertyDescriptor,然后构建 AutowiredMethodElement 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 查找方法上的 autowire 注解
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
// 忽略日志
return;
}
if (method.getParameterCount() == 0) {
// 忽略日志
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);

// 构建 autowire 元数据
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});

构建 InjectionMetadata

获取到 AutowiredFieldElementAutowiredMethodElement 之后,就可以构建 InjectionMetadata 依赖注入元数据了。

1
return new InjectionMetadata(clazz, elements);

它的两个参数分别为当前 bean 对应的 class 和从 class 上解析到的依赖注入信息

1
2
3
4
5
6
7
8
9
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();

// 遍历获取到的 field 依赖注入信息
currElements.add(new AutowiredFieldElement(field, required));

// 遍历获取到的 method 依赖注入信息
currElements.add(new AutowiredMethodElement(method, required, pd));

elements.addAll(0, currElements);

完成依赖注入

完成依赖注入的关键在于 InjectionMetadata 类。前面通过 MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition 回调方法完成了 InjectionMetadata 的构建,但还没有真正地去注入依赖 bean。

依赖 bean 的注入是通过 InstantiationAwareBeanPostProcessor 接口的 postProcessProperties 回调方法触发的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 解析依赖注入的注解
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 执行依赖注入
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;
}

因为在 postProcessMergedBeanDefinition 调用 findAutowiringMetadata 方法时已经完成了依赖注入元数据的构建,所以在 postProcessProperties 调用时是直接从缓存中获取到的。

这里依赖注入的核心是 InjectionMetadatainject 方法调用,它的实现是遍历所有的 InjectedElement 对象,分别调用其 inject 方法完成依赖注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// injectedElements 就是构建 InjectionMetadata 时传入的一个参数
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);
}
element.inject(target, beanName, pvs);
}
}
}

AutowiredFieldElement

AutowiredFieldElement 继承自 InjectionMetadata.InjectedElement,用于表示 field 上的依赖注入信息,它的类继承结构如下图所示:

image-20200408012835657

我们主要关注的是它的 inject 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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 {
// 获取所需的 bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
// 注册依赖关系
registerDependentBeans(beanName, autowiredBeanNames);

if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}

// 设置属性值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}

它的主要流程如下:

  1. 构造 DependencyDescriptor 依赖描述信息
  2. 解析依赖:从 beanFactory 获取所需的 bean
  3. 注册依赖关系
  4. 设置属性值

可以看出 field 依赖注入的核心是从 beanFactory 中获取所需 bean,通过反射设置属性值。

AutowiredMethodElement

AutowiredMethodElement 也继承自 InjectionMetadata.InjectedElement,用于表示 method 上的依赖注入信息,它的类继承结构如下图所示:

image-20200408013427859

同样看一下它的 inject 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];

Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();

for (int i = 0; i < arguments.length; i++) {
// 构造依赖描述
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 获取所需的 bean
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
Object[] cachedMethodArguments = new Object[paramTypes.length];
System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length);

// 注册依赖关系
registerDependentBeans(beanName, autowiredBeans);

if (autowiredBeans.size() == paramTypes.length) {
Iterator<String> it = autowiredBeans.iterator();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
// 调用方法设置依赖 bean
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

它的主要流程与 AutowiredFieldElementinject 方法类似:

  1. 构造 DependencyDescriptor 依赖描述信息
  2. 解析依赖:从 beanFactory 获取所需的 bean
  3. 注册依赖关系
  4. 调用方法设置依赖 bean

因为参数可能有多个,所以这里需要循环处理每个参数

0%