- 如果根节点或者子节点采用默认命名空间的话,则调用
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 加载