本文主要基于 Spring 5.0.6.RELEASE
摘要: 原创出处 http://cmsblogs.com/?p=2697 「小明哥」,谢谢!
作为「小明哥」的忠实读者,「老艿艿」略作修改,记录在理解过程中,参考的资料。
获取 XML Document 对象后,会根据该对象和 Resource 资源对象调用 XmlBeanDefinitionReader#registerBeanDefinitions(Document doc, Resource resource) 方法,开始注册 BeanDefinitions 之旅。代码如下:
// AbstractBeanDefinitionReader.java |
<1>处,调用#createBeanDefinitionDocumentReader()方法,实例化 BeanDefinitionDocumentReader 对象。
FROM 《Spring 源码深度解析》P16 页
定义读取 Document 并注册 BeanDefinition 功能
<2>处,调用BeanDefinitionRegistry#getBeanDefinitionCount()方法,获取已注册的 BeanDefinition 数量。<3>处,调用#createReaderContext(Resource resource)方法,创建 XmlReaderContext 对象。<4>处,调用BeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext)方法,读取 XML 元素,注册 BeanDefinition 们。<5>处,计算新注册的 BeanDefinition 数量。
1. createBeanDefinitionDocumentReader
#createBeanDefinitionDocumentReader(),实例化 BeanDefinitionDocumentReader 对象。代码如下:
/** |
documentReaderClass的默认值为DefaultBeanDefinitionDocumentReader.class。关于它,我们在后续的文章,详细解析。
2. registerBeanDefinitions
BeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext) 方法,注册 BeanDefinition ,在接口 BeanDefinitionDocumentReader 中定义。代码如下:
public interface BeanDefinitionDocumentReader { |
从给定的 Document 对象中解析定义的 BeanDefinition 并将他们注册到注册表中。方法接收两个参数:
doc方法参数:待解析的 Document 对象。readerContext方法,解析器的当前上下文,包括目标注册表和被解析的资源。它是根据 Resource 来创建的,见 「3. createReaderContext」 。
2.1 DefaultBeanDefinitionDocumentReader
BeanDefinitionDocumentReader 有且只有一个默认实现类 DefaultBeanDefinitionDocumentReader 。它对 #registerBeanDefinitions(...) 方法的实现代码如下:
DefaultBeanDefinitionDocumentReader 对该方法提供了实现:
|
<1>处,创建 BeanDefinitionParserDelegate 对象,并进行设置到delegate。BeanDefinitionParserDelegate 是一个重要的类,它负责解析 BeanDefinition。代码如下:FROM 《Spring 源码深度解析》P16
定义解析 XML Element 的各种方法
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
// 创建 BeanDefinitionParserDelegate 对象
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
// 初始化默认
delegate.initDefaults(root, parentDelegate);
return delegate;
}<2>处,检查<beans />根标签的命名空间是否为空,或者是 http://www.springframework.org/schema/beans 。<2.1>处,判断是否<beans />上配置了profile属性。不了解这块的胖友,可以看下 《《Spring3自定义环境配置》》 。<2.2>处,使用分隔符切分,可能有多个 profile 。<2.3>处,判断,如果所有 profile 都无效,则return不进行注册。
<4>处,调用#parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法,进行解析逻辑。详细解析,见 「3.1 parseBeanDefinitions」 。<3>/<5>处,解析前后的处理,目前这两个方法都是空实现,交由子类来实现。代码如下:protected void preProcessXml(Element root) {}
protected void postProcessXml(Element root) {}
2.1.1 parseBeanDefinitions
#parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 方法,进行解析逻辑。代码如下:
/** |
- Spring 有两种 Bean 声明方式:
- 配置文件式声明:
<bean id="studentService" class="org.springframework.core.StudentService" />。对应<1>处。 - 自定义注解方式:
<tx:annotation-driven>。对应<2>处。
- 配置文件式声明:
<1>处,如果根节点或子节点使用默认命名空间,调用#parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法,执行默认解析。代码如下:private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // import
importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // alias
processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // bean
processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // beans
// recurse
doRegisterBeanDefinitions(ele);
}
}- 详细的解析,见后续文章。
<2>处,如果根节点或子节点不使用默认命名空间,调用BeanDefinitionParserDelegate#parseCustomElement(Element ele)方法,执行自定义解析。详细的解析,见后续文章。
3. createReaderContext
#createReaderContext(Resource resource) 方法,创建 XmlReaderContext 对象。代码如下:
private ProblemReporter problemReporter = new FailFastProblemReporter(); |
关于 XmlReaderContext 的详细解析,见后续文章。
4. 小结
至此,XmlBeanDefinitionReader#doLoadBeanDefinitions(InputSource inputSource, Resource resource) 方法中,做的三件事情已经全部分析完毕,下面将对 BeanDefinition 的解析过程做详细分析说明。
另外,XmlBeanDefinitionReader#doLoadBeanDefinitions(InputSource inputSource, Resource resource) 方法,整体时序图如下:
- 红框部分,就是 BeanDefinition 的解析过程。