Spring 源码分析总结篇一: Spring IOC篇

一、前言

本文,是本人在阅读源码过程中的一些内容整理和总结。
全文仅代表个人理解和意见,故难免出现错误,如若发现,欢迎指正。十分谢谢。

本文所涉及的文章内容均在 : Spring源码分析:全集整理


关于 :ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessor 的详细分析,可以在 Spring源码分析:全集整理 中找到对应的分析文章。

二、正文

2.1 Spring IOC 实现个人感觉最重要的两个类

  • ConfigurationClassPostProcessor : 完成了类的扫描和配置了的解析

  • AutowiredAnnotationBeanPostProcessor : 完成了非 Property 的属性的注入


  1. ConfigurationClassPostProcessorBeanFactoryPostProcessor子类。

    postProcessBeanDefinitionRegistry : 解析所有需要注册的配置类
    postProcessBeanFactory :对Full类型进行代理增强,保证@Bean方法正确语意。

  2. AutowiredAnnotationBeanPostProcessorBeanPostProcessor 子类,完成了@Autowired、@Value、@Inject注解的解析注入功能。也就是说 AutowiredAnnotationBeanPostProcessor 中才完成了属性的注入。

2.2 Spring什么时候扫描的包路径?

Spring在启动时候会将启动类注册到Spring容器中。在ConfigurationClassPostProcessor中,会将启动类作为配置类进行解析。由于启动类上面有@ComponentScan注解,所以在ConfigurationClassParser# doProcessConfigurationClass中会解析这个注解, 根据解析后的路径通过
his.componentScanParser, parse (componentScan,sourceClass.getMetadata () .getClassName())进行扫描,注册扫描到的需要注入的类(被@Component 修饰的类)并进行注入,如果有配置类再进行递归的配置类解析。(扫描是在 方法 org.springframework.context. annotation.ClassPathBeanDefinitionScanner#doScan中进行的扫描,但是我偷懒了没看具体实现)

2.2 ConfigurationClassPostProcessor 的解析流程

. ConfigurationClassPostProcessor完成了对各种配置类的扫描,并将其引入的bean注册到BeanFactory中。

  1. postProcessBeanDefinitionRegistry方法逻辑(完成了各种配置类的解析和注册)

  2. 获取所有BeanFactory中的BeanDefinition

  3. 遍历所有BeanDefinition,筛选出full或者lite 配置类,等待下一步处理。

    • Full 规则 :被 @Configuration 注解修饰 && proxyBeanMethods属性为true (默认为true)
    • Lite规则:被@Component. @ComponentScan, @Import. @ImportResource修饰的类或者类中有被@Bean修饰的方法(该方法会被包装成一个 BeanDefinition)
  4. 遍历所有full 和lite配置类,解析各种注解,对配置类进行进一步的解析(因为Lite的配置类需要二次解析,所以这里主要是二次解析)

    • @Component进行解析:即如果当前配置类被@Component注解修饰,则去解析其内部类(包括静态内部类和非静态内部类)是否是配置类,如果是,递归解析发现的配置类。
    • :对@PropertySource进行解析:解析出其指定的配置文件内容,并保存到environment 中
    • :对@ComponentScan注解的解析:获取注解指定路径,进行扫描注册。对新扫描出来的BeanDefinition进行判定是否是配置类,如果是,则递归去解析配置类
    • @Import、ImportSelector、ImportBeanDefinitionRegistrar的解析:因为这三个注解或接口,本质上完成的功能是.一样的,都是引入类。所以在这一部分的处理上只是区分了不同的类型
    • @ImportResource注解的解析:提取出@ImportResource注解的属性,保存到configClassimportedResources属性中
    • 对被@Bean修饰的方法的解析:提取出@Bean修饰的方法,保存的到configClassbeanMethods属性中.
    • 对接口的默认方法解析:保存的到configClassbeanMethods属性中
    • 对父类的解析:如果存在父类,则递归其父类进行解析。
  5. 遍历所有的配置类,进行注册

    • 处理引入的配置类:将配置类信息封装成BeanDefinition,并注册到BeanFactory
    • 处理@Bean修饰的方法将@Bean修饰的方法封装成BeanDefinition,并注册到BeanFactory
    • 处理@ImportResource注解引入的资源文件,获取到BeanDefinition并注册。
    • 处理@Import、ImportSelector、ImportBeanDefinitionRegistrar引入的类,注册到BeanFactory中。

补充:4.1 中为什么要解析@Component?

  • 因为过滤出来的配置类可能没有被@Component修饰,比如仅仅是,可能是Spring硬编码注入或者我们通过编码注入的bean。如果没有使用@Component注解修饰,就没必要解析其内部类是否是配置类。比如最简单的就是spring.factories文件中引入的类。可能满足配置类判定,但并没有被@Component修饰

2.3 AutowiredAnnotationBeanPostProcessor 的解析流程

AutowiredAnnotationBeanPostProcessor 完成@Autowired. @Value、 @Inject注解的功能, 完成了
Spring的注入

  1. determineCandidateConstructors 方法 :筛选出当前bean中能作为构造注入的构造函数列表。用于构造注入

    • 处理了@Lookup注解,将@Lookup注解标注的方法保存了起来。这一步和构造函数的筛选没有任何关系
    • 挑选候选构造函数。简单逻辑就是有注解修饰选注解修饰的构造函数,没有的话使用默认无参构造函数没有无参构造函数,再没有返回null.
  2. postProcessProperties 方法 :筛选Bean中需要注入的属性,进行属性注入。用于设置注入和注解注入遍历每个属性,找到被注入注解修饰的属性。保存到currElements中。遍历每个方法,找到被注入注解修饰的方法, 保存到currElements中。随后遍历currElements, 通过resolveDependency方法将方法或者属性注入(resolveDependency方法是在populateBean方法中按照类型注入时调用的方法)这里可以知道,按照顺序遍历,方法的属性在属性的后面,自动注入时,方法的注入结果会把注解属性的注入覆盖掉。

注: Spring注入的方式分为三种 :构造注入、设值注入、注解注入。在AutowiredAnnotationBeanPostProcessor 中处理的实际是设置注入和注解注入。

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/107122196