前戏

Spring 提供了一个读取配置文件的接口:BeanDefinitionReader,理论上读取 Spring 的配置文件需要实现这个接口,但也不强制。

Note that a bean definition reader does not have to implement this interface. It only serves as suggestion for bean definition readers that want to follow standard naming conventions.

它有三个主要的实现类: Spring5.2 源码学习 - 读取 XML 的 Bean 配置信息 - 图1分别表示:

  • XmlBeanDefinitionReader:具体实现类,可以从 XML 文件读取 Bean 定义信息;
  • PropertiesBeanDefinitionReader:具体实现类,可以从 Properties 文件读取 Bean 定义信息;
  • GroovyBeanDefinitionReader:具体实现类,可以读取 Groovy 语言写的 Bean 的定义信息。

因为读取配置信息非必须实现这个接口,所以你还可以看到其他读取 Bean 的定义信息的类:

  • JdbcBeanDefinitionReader
  • AnnotatedBeanDefinitionReader
  • ConfigurationClassBeanDefinitionReader

首先通过接口和抽象类了解下都需要做什么操作?
大概的意思:从某处加载定义信息,解析成 BeanDefinition,注册进 BeanDefinitionRegistry;
AbstractBeanDefinitionReader 对这个过程进行了实现,把 loadBeanDefinitions(Resource resource) 交给了子类去处理。当然这个过程还包括 Bean 定义校验,SAX 对 XML 的解析,处理环境变量等;
BeanDefinitionRegistry 上面还有一个接口 AliasRegistry,表示利用别名操作注册信息;
这个Bean注册意思:解析好的 BeanDefinition 相关信息存储到一个 Map 容器中。

具体过程

类流转示意图:

Spring5.2 源码学习 - 读取 XML 的 Bean 配置信息 - 图2

Bean 定义具体是如何读取注册的?这个时候看源码中的单元测试最合适!

  1. @Test
  2. public void withOpenInputStreamAndExplicitValidationMode() {
  3. SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
  4. Resource resource =
  5. new InputStreamResource(getClass().getResourceAsStream("test.xml"));
  6. XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
  7. reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
  8. reader.loadBeanDefinitions(resource);
  9. testBeanDefinitions(registry);
  10. }