Spring 源码:bean的实例化、注解收集、依赖注入(DI)

 2023-01-22
原文作者:一支野菊花 原文地址:https://juejin.cn/post/7029882641721589791

上一篇【spring源码-5】bean的实例化(2)主逻辑

引题

上篇回顾:

202301012104403151.png

556 行:此时堆内存中已经存在了实例对象,但是属性还没有赋值。
568 行:注解收集,依赖注入

注解收集

applyMergedBeanDefinitionPostProcessors

202301012104413862.png

202301012104421033.png

该方法是对 PostProcessor 典型的应用。
循环所有的 PostProcessor 类,调用 MergedBeanDefinitionPostProcessor 类的 postProcessMergedBeanDefinition()。

1. CommonAnnotationBeanPostProcessor

完成了 @Resource 注解的收集和对 @PostConstruct,@PreDestroy 注解的支持。

202301012104426464.png 注意:首先构造方法中给父类 InitDestroyAnnotationBeanPostProcessor 设置了注解信息。

202301012104431735.png

294 行:扫描 @PostConstruct,@PreDestroy 注解。

202301012104438216.png

202301012104445767.png

202301012104455358.png 232 行:使用 ReflectionUtils 工具类循环类中所有的方法。
233 行 - 234 行:如果有 @PostConstruct 注解,包装成 LifecycleElement 对象并添加到 map 中。
240 行 - 241 行:如果有 @PreDestroy 注解,也包装成 LifecycleElement 对象并添加到 map 中。
254 行:最后将类、有 @PostConstruct 、@PreDestroy 注解方法的集合 包装成 LifecycleMetadata 对象返回。

295 行:扫描 @Rsource 注解。

202301012104463059.png

2023010121044724810.png

2023010121044798311.png 366 行:循环类中所有的 属性 ,如果有 @Rsource 注解就包装成 ResourceElement 对象并添加到集合中。
389 行:循环类中所有的 方法 ,如果有 @Rsource 注解就包装成 ResourceElement 对象并添加到集合中。
436 行:最终将类、和含有 @Rsource 注解 的方法和属性包装成 InjectionMetadata 对象并返回。


2. AutowiredAnnotationBeanPostProcessor

2023010121044857612.png

对 @Autowired 和 @Value 注解的属性和方法的收集。

2023010121044928313.png

2023010121044978014.png

2023010121045047415.png

2023010121045133516.png

2023010121045204817.png 收集过程与 上面 @Rsource 注解类似。

到此已经完成了注解的收集。

依赖注入 (DI)

populateBean

2023010121045291018.png 调用到本类方法:

2023010121045371019.png 1382 行:BeanPostProcessors 的应用。

实现 InstantiationAwareBeanPostProcessor 类,自定义控制依赖注入

应用示例

2023010121045490620.png


主逻辑

2023010121045566321.png 1442 行:XML配置文件标签形式注入逻辑。
1425 行:老版本逻辑。
1420 行:BeanPostProcessors 的应用。

调用 InstantiationAwareBeanPostProcessor 类的 postProcessProperties()

AutowiredAnnotationBeanPostProcessor 类完成对@Resource @Autowired 注解的注入。

2023010121045637322.png 397 行:拿到前面收集到的注解信息。
399 行:调用到 InjectionMetadata 类中。

2023010121045724123.png 130 行:循环前面收集到的 带有 @Autowired @Rsource 注解属性以及方法的集合。并逐个调用。inject() 有两个实现,分别是处理属性和方法的。

2023010121045788624.png

注入属性

2023010121045844425.png 640 行:如果注入的是引用类型,会触发 getBean() 实例化需要注入的对象(实例化逻辑就是之前说到的)。
667 行:通过反射方式把属性设置为可操作性的。
668 行:给属性设置值。

注入方法

2023010121050006126.png 754 - 755 行:也是通过反射将方法设置为可操作的,然后调用。同样,如果方法形参是引用类型,也会触发 getBean() 操作。


总结

注解收集

  1. CommonAnnotationBeanPostProcessor 收集 @PostConstruct、@PreDestroy、@Resource 注解。

  2. AutowiredAnnotationBeanPostProcessor 收集 @Autowired、@Value 注解。 通过 BeanPostProcessor 完成收集过程。 依赖注入(DI)
    对含有 @Autowired、@Value、@Resource 注解的属性和方法,通过反射完成注入。

  3. 注入属性,如果是引用类型,会触发 getBean() 实例化需要注入的对象(实例化逻辑就是之前说到的)。

  4. 注入方法时,如果方法形参是引用类型,也会触发 getBean() 操作。

注:本文通过源码 + 行说明的方式进行描述,若不好理解可留言。本文仅为个人学习记录,有错误的地方,请大佬们指正。

下一篇【spring源码-7】bean的实例化(4)后置处理