如果根节点或者子节点采用默认命名空间的话,则调用 parseDefaultElement() 进行默认标签解析
否则调用 delegate.parseCustomElement() 方法进行自定义解析
默认标签解析过程,源码如下:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 对 import 标签的解析
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 对 alias 标签的解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 对 bean 标签的解析
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 对 beans 标签的解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
分别是对四种不同的标签进行解析,分别是 import、alias、bean、beans
import 标签的处理
Spring 提供了一个分模块的思路,利用 import 标签,例如我们可以构造一个这样的 spring.xml
Spring 利用 importBeanDefinitionResource() 方法完成对 import 标签的解析
解析 import 过程较为清晰,整个过程如下:
获取 source 属性的值,该值表示资源的路径
解析路径中的系统属性,如"${user.dir}"
判断资源路径 location 是绝对路径还是相对路径
如果是绝对路径,则调递归调用 Bean 的解析过程,进行另一次的解析
如果是相对路径,则先计算出绝对路径得到 Resource,然后进行解析
通知监听器,完成解析
判断绝对路径的规则如下:
以 classpath*: 或者 classpath: 开头为绝对路径
能够通过该 location 构建出 java.net.URL为绝对路径
根据 location 构造 java.net.URI 判断调用 isAbsolute() 判断是否为绝对路径
如果 location 为绝对路径则调用 loadBeanDefinitions(),该方法在 AbstractBeanDefinitionReader 中定义
如果是相对路径则会根据相应的 Resource 计算出相应的绝对路径,
然后根据该路径构造一个 Resource
若该 Resource 存在,则调用 XmlBeanDefinitionReader.loadBeanDefinitions() 进行 BeanDefinition 加载
否则构造一个绝对 location ,调用 AbstractBeanDefinitionReader.loadBeanDefinitions() 方法,与绝对路径过程一样
整个过程比较清晰明了:
获取 source 属性值,得到正确的资源路径,然后调用 loadBeanDefinitions()方法进行递归的 BeanDefinition 加载