是谁去读取 BeanDefinition 的?

是谁去读取 BeanDefinition 的?

💡 原文中文,约9400字,阅读约需23分钟。
📝

内容提要

本文介绍了 Spring 框架中 BeanDefinition 的加载机制,主要通过 BeanDefinitionReader 接口及其实现类(如 XmlBeanDefinitionReader)读取 XML 配置文件。解析过程涉及注册器、资源加载器和类加载器,最终将 BeanDefinition 注册到容器中,并详细描述了 XML 文件的解析流程及相关方法的实现。

🔎

延伸解读

BeanDefinitionReader 的职责与设计

BeanDefinitionReader 接口定义了读取 BeanDefinition 的核心规范,包括获取注册器、资源加载器、类加载器和 beanName 生成器的方法。其 loadBeanDefinitions 方法有多个重载,但最终都委托给 loadBeanDefinitions(Resource resource) 执行。这种设计将资源定位与具体解析逻辑分离,便于扩展不同格式的配置文件。

XML 配置加载的编码与循环依赖防护

XmlBeanDefinitionReader 在加载 XML 时,会先将 Resource 包装为 EncodedResource 以处理编码,避免乱码。同时使用 ThreadLocal 记录当前正在加载的资源,若同一资源被重复加入则抛出异常,防止因 import 导致的循环加载。这些细节体现了 Spring 在配置解析阶段的健壮性考虑。

XML 解析流程与标签处理

解析 XML 时,Spring 先将文件转为 Document 对象,再通过 BeanDefinitionDocumentReader 遍历节点。默认标签如 import、alias、bean、beans 由 parseDefaultElement 处理,自定义标签则交给 delegate.parseCustomElement。对于 beans 标签会递归解析,而 bean 标签最终会解析属性并注册为 GenericBeanDefinition。

BeanDefinition 注册与事件通知

在 processBeanDefinition 中,解析完 bean 标签后会检查是否需要装饰(如 p 命名空间属性),然后通过 BeanDefinitionReaderUtils.registerBeanDefinition 将 BeanDefinition 注册到容器的 Map 中,key 为 beanName。注册完成后还会触发组件注册事件,方便监听器进行后续处理。

❓

Q&A

BeanDefinition 是如何加载的?

BeanDefinition 主要通过 BeanDefinitionReader 接口及其实现类(如 XmlBeanDefinitionReader)来加载。

XmlBeanDefinitionReader 的作用是什么?

XmlBeanDefinitionReader 是用于读取 XML 配置文件的实现类,重写了 loadBeanDefinitions 方法以加载配置。

loadBeanDefinitions 方法的主要作用是什么?

loadBeanDefinitions 方法用于根据传入的配置文件加载 BeanDefinition,最终调用 loadBeanDefinitions(Resource resource) 方法。

如何处理 XML 配置文件的编码问题?

XmlBeanDefinitionReader 通过 EncodedResource 对象处理配置文件的编码问题,以防止乱码。

registerBeanDefinitions 方法的作用是什么?

registerBeanDefinitions 方法用于解析 Document 对象并将其注册为 BeanDefinition,返回注册的数量。

BeanDefinitionDocumentReader 接口的作用是什么?

BeanDefinitionDocumentReader 接口用于解析 Document 对象并注册 BeanDefinition,其实现类为 DefaultBeanDefinitionDocumentReader。

🏷️

标签

➡️

继续阅读