近期想扩展定义自己的配置文件的标签,采用以前写的而一个篇扩展的方式,只能扩展自己的附加的类,无法实现组装bean的方式,所以针对spring对默认的命名空间的解析bean的方式进行分析
主要的分析代码都在DefaultBeanDefinitionDocumentReader中的方法registerBeanDefinitions中
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
preProcessXml(root);
parseBeanDefinitions(root, delegate);
postProcessXml(root);
其实preProcessXml(root)和postProcessXml(root)供去扩展,默认没有实现任何功能
主要是parseBeanDefinitions(root, delegate);
if (delegate.isDefaultNamespace(root.getNamespaceURI())) { //TODO:core bean处理
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
String namespaceUri = ele.getNamespaceURI();
if (delegate.isDefaultNamespace(namespaceUri)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele); //TODO:解析bean
}
}
}
}
else {
delegate.parseCustomElement(root); //自定义元素
}
如果是默认的命名空间采用parseDefaultElement(ele, delegate)去处理,如果是自定义的delegate.parseCustomElement(ele)去处理
首先查看 default的解析,default包含如下几个标签,分别解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) { //TODO:处理xml中定义的bean元素
processBeanDefinition(ele, delegate);
}
}
我们主要关注的是bean的解析,所以只是查看一下processBeanDefinition(ele, delegate);
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
解析完成,组装成BeanComponentDefinition
自定义标签的解析方式
String namespaceUri = ele.getNamespaceURI();
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
通过方法查看出来,如果是自定义的标签,就读取在spring.handler中配置的Handler进行配置的解析