【Spring源码】10.IOC之@Autowired,@Val

前言
上一篇讲了 ,在bean的实例化过程中, 首先 就是通过 FactoryMethod 或者 构造方法 来创建出对象,对应的是AbstractAutowireCapableBeanFactory.doCreateBean 的这部分代码。

这篇将 介绍的 是 接下来的这段代码 :
其主要作用 就是 通过 预置好的BeanPostProcessor类 来进行 @Autowired/@Value的属性和方法,@PreDestory / @PostConstruct 的方法 的收集工作, 并且 放到BeanDefinition对象里的容器里 ,为 后续的 依赖注入,以及调用生命周期 方法 做准备。

循环所有的BeanPostProcessor类型,如果是MergedBeanDefinitionPostProcessor类型(这个类型的主要就是用来做收集工作的)。

1. @Autowired,@Value
负责收集@Autowired,@Value的属性和方法的是AutowiredAnnotationBeanPostProcessor这个类。
点进AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName)

- findAutowiringMetadata(beanName, beanType, null) :收集@Autowired,@Value的属性和方法,封装到InjectionMetadata 对象里
- InjectionMetadata .checkConfigMembers(bd) : 将收集好的属性和方法 设置到beanDefinition 里。
1.1 收集@Autowired,@Value的属性和方法
1.1.1 InjectionMetadata 类
内部有targetClass 和 装收集到属性和方法的集合

1.1.1.1 InjectedElement
其实就是 jdk反射里的Member对象的包装,Member 又是 Field和Method 对象的 父类.

1.1.2. findAutowiringMetadata 开始收集
1.1.2.1 缓存
这里又是一个缓存, 缓存是AutowiredAnnotationBeanPostProcessor中的injectionMetadataCache对象。
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
缓存的Key是 beanName或者Class的名称, 所有的bean 收集好的属性和方法都缓存在AutowiredAnnotationBeanPostProcessor对象里的injectionMetadataCache 中。

1.1.2.2 缓存里没有,开始收集 buildAutowiringMetadata(clazz)
1.2.2.2.1 属性的收集

循环该Class对象的所有 Fields, 然后判断是否存在@autowired/@Value注解且为非静态的。
- findAutowiredAnnotation() 查找注解

autowiredAnnotationTypes 是AutowiredAnnotationBeanPostProcessor 在构造方法 就 提前内置好的 要处理的注解的 集合

AutowiredFieldElement
这个类是InjectedElement的子类,专门用来包装有@Autowired和@Value注解的属性,还多了 @Autowired的required属性的值。

所以这段代码的作用是 ,只要是@Autowired和@Value 注解,都可以被收集。如果符合,就创建AutowiredFieldElement对象,加到currElements 中
1.2.2.2.2 方法的收集
有@autowired/@Value注解且为非静态的方法的收集原理 和 收集属性 是一样的:
循环每个方法, 判断是否符合注解, 符合的话将Method 和 @Autowired的required值封装到 AutowiredMethodElement 对象里, 加到 currElements容器里。

AutowiredMethodElement类 和 AutowiredFieldElement类 差不多,装Method和Field的区别。同样继承的InjectedElement类。

1.2.2.2.3 返回InjectionMetadata对象
将刚才收集到的属性和方法全部加到elements里,

然后 new 出InjectionMetadata 对象


1.1.2.3 建立InjectionMetadata 的缓存
包装的 所有带有@Autowired和@Value的属性和方法的 InjectionMetadata 对象创建出来之后, 缓存到AutowiredAnnotationBeanPostProcessor类里的injectionMetadataCache中:{beanName || beanClassName : InjectionMetadata对象},下次从缓存中取。

1.1.3 将收集到的属性和方法设置到BeanDefinition里
收集完之后,将InjectionMetadata 对象里收集到的属性和方法 放到BeanDefinition对象里的 externallyManagedConfigMembers 集合中


至此 @Autowired,@Value注解的 方法和 属性全部收集完毕。
2. @Resource
@Resource的收集是由CommonAnnotationBeanPostProcessor类来完成的
点进CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()

和 收集 @autowired/ @Value 差不多的流程

2.1 先是创建InjectionMetadata 对象

2.1.1 判断缓存

2.1.2 开始收集 buildResourceMetadata
2.1.2.1 属性
其他的判断分支不用看, 没啥用

2.1.2.2 方法

2.1.3 返回InjectionMetadata对象

2.1.3 建立缓存

2.2 将收集到的属性和方法设置到BeanDefinition里

3. @PostConstruct和@PreDestroy
这两个注解是用在方法上的,他们的收集功能由CommonAnnotationBeanPostProcessor的父类,InitDestroyAnnotationBeanPostProcessor来完成, 就在CommonAnnotationBeanPostProcessor收集@Resource 的代码 之前,调用了 super.postProcessMergedBeanDefinition().


收集的过程 和 前面哪几个注解的差不多。
3.1 收集 @PostConstruct方法和@PreDestroy方法
收集到的属性会方法LifecycleMetadata对象里,这个对象里面有两个属性专门用来装 有这两个注解的 方法。

点进findLifecycleMetadata(beanType)。
3.1.1 缓存

3.1.2 开始收集
点进buildLifecycleMetadata(clazz)
循环方法,有@PostConstruct 放到一个集合里,有@PreDestroy注解的放到另一个集合里

InitDestroyAnnotationBeanPostProcessor 里的 initAnnotationType,destroyAnnotationType 是在子类CommonAnnotationBeanPostProcessor实例化的时候设置的

3.1.3 返回LifecycleMetadata对象

3.1.4 建立缓存

3.2 将收集到的方法放到BeanDefinition中
- 把解析出来的含有@PostConstruct注解的方法添加到 bd的 externallyManagedInitMethods<Method>
- 把解析出来的含有@PreDestroy 注解的方法 添加 bd的 externallyManagedDestroyMethods<Method>


4. 总结
收集完了, 以后bean的依赖注入和调用方法 时 就从这里 获取需要处理的属性和方法就行了。
4.1 几个BeanPostProcessor和各自负责的工作:
- AutowiredAnnotationBeanPostProcessor : 收集@Autowired,@Value的属性和方法
- CommonAnnotationBeanPostProcessor : 收集@Resource
- 并调用父类InitDestroyAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()来收集@PostConstruct,@PreDestroy
4.2 BeanDefinition中装收集好的成员的 容器
@Nullable
// 装@Autowired,@Value,@Resource注解 的 属性和方法
private Set<Member> externallyManagedConfigMembers;
@Nullable
// 装@PostConstruct注解 的方法
private Set<String> externallyManagedInitMethods;
@Nullable
// 装 有@PreDestroy注解修饰的 方法
private Set<String> externallyManagedDestroyMethods;