Spring IOC 配置元数据的解析

114 阅读2分钟

概述

前面介绍过,Spring IoC 容器的输入之一,配置元数据,它描述了我们要创建的beans的各种属性以及bean之间的依赖关系。Spring IoC容器要使用这些数据来实例化、配置、组装并管理我们需要的beans。

本文介绍配置元数据的解析,即由xml文档/java配置的元数据,如何由容器的实现类使用各种reader加载解析为BeanDefinition存储在容器中。

  • xml配置元数据的解析
  • @Component注解的Bean如何由Spring识别解析
  • Java配置元数据(@Configuration、@Bean)的解析
  • Spring Boot项目的Bean怎么解析出来的

xml配置元数据的解析

这是最原始的方法,在xml中定义bean,然后使用ClassPathXmlApplicationContext,读取xml文件:

  1. ClassPathXmlApplicationContext创建,refresh
  2. 通过BeanDefinitionReader进行xml文件资源读取,doc xml文档解析,进行BeanDefinition的注册

image-20220213174822166

包扫描@Component的Bean解析

xml配置包扫描

处理主要过程

  1. 解析到xml标签,通过特殊的命名空间找到特殊的xml解析器
  2. 通过特定的ComponentScanBeanDefinitionParser进行解析,里面配置了ClassPathBeanDefinitionScanner,使用默认includeFilter扫描@Component注解的类
  3. 注册为BeanDefinition

堆栈:

image-20220213164826996

AnnotationConfigApplicationContext

@ComponentScan @Configuration注解,Java注解配置Context,基本过程:

  1. 初始化context时注册BeanFactoryPostProcessor,ConfigurationClassPostProcessor,专门用来处理@Configuration
  2. 在ApplicationContext刷新时,调用ConfigurationClassPostProcessor,从beanFactory中获取到@Configuration注解的类,然后进行处理
  3. 会检测到@Configuration注解类上同时也有@ComponentScan注解时,便又开始使用ClassPathBeanDefinitionScanner进行扫描包

image-20220213171404251

image-20220213171202472

Java配置的解析

还是使用AnnotationConfigApplicationContext,过程跟之前类似:

  1. 初始化context时注册BeanFactoryPostProcessor,ConfigurationClassPostProcessor,专门用来处理@Configuration
  2. 解析@Configuration类时,会获取@Bean方法,configClass.getBeanMethods()
  3. 然后进行BeanDefinition的注册,会把方法记录在BeanDefinition中

image-20220213172432560

Spring Boot Bean配置解析

Spring Boot应用启动后:

  1. 首先使用的Context实现是AnnotationConfigServletWebServerApplicationContext,类似AnnotationConfigApplicationContext,也使用了AnnotatedBeanDefinitionReader,init时就先注册了解析@Configuration类用的ConfigurationClassPostProcessor(一个BeanFactoryPostProcessor)

    image-20220213173029433

  2. 然后先把启动类当作一个Bean load了(省略证明),启动类的@SpringBootApplication注解上有个@Configuration、@ComponentScan注解,跟之前就串上了吧,

    image-20220213174128793

  3. refresh时,使用ConfigurationClassPostProcessor,处理@ComponentScan,basepackage为空时,使用启动类所在的包名作为扫描包,进行扫描解析

image-20220213174011672