参考文章:
回到之前bean注册中说的标签解析地方,我们来看下标签具体是如何解析的。
//如果该节点使用默认命名空间,执行默认解析
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
// 如果该节点非默认命名空间,执行自定义解析
else {
delegate.parseCustomElement(ele);
}
根据上面代码可以看出来主要的解析方式有两种。
- 如果根节点或者子节点采用默认命名空间的话,则调用
#parseDefaultElement(...)
方法,进行默认标签解析 BeanDefinitionParserDelegate#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
自定义解析
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 获取 namespaceUri
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 根据 namespaceUri 获取相应的 Handler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 调用自定义的 Handler 处理
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
- 调用
#getNamespaceURI((Node node)
方法,获取namespaceUri
- 调用
XmlReaderContext#getNamespaceHandlerResolver()
方法,获得命名空间的解析器 - 调用
NamespaceHandlerResolver#resolve(String namespaceUri)
方法,根据namespaceUri
获取相应的 Handler 对象。这个映射关系我们在spring.handlers
中已经定义了 - 调用
NamespaceHandler#parse(Element element, ParserContext parserContext)
方法,调用自定义的 Handler 处理