曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上) (4)

进入BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element):

public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); //这里,通过namespaceUri,查找对应的handler,我们这里,会得到:org.springframework.beans.factory.xml.UtilNamespaceHandler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } // 调用org.springframework.beans.factory.xml.UtilNamespaceHandler,解析constant元素 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } NamespaceHandler概览

好了,我们看看这个UtilNamespaceHandler:

public class UtilNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("constant", new ConstantBeanDefinitionParser()); registerBeanDefinitionParser("property-path", new PropertyPathBeanDefinitionParser()); registerBeanDefinitionParser("list", new ListBeanDefinitionParser()); registerBeanDefinitionParser("set", new SetBeanDefinitionParser()); registerBeanDefinitionParser("map", new MapBeanDefinitionParser()); registerBeanDefinitionParser("properties", new PropertiesBeanDefinitionParser()); } private static class ConstantBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser { @Override protected Class getBeanClass(Element element) { return FieldRetrievingFactoryBean.class; } @Override protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) { String id = super.resolveId(element, definition, parserContext); if (!StringUtils.hasText(id)) { id = element.getAttribute("static-field"); } return id; } } ...省略 }

这里,很明显,UtilNamespaceHandler定义了每个元素,该由什么类来处理。

namespaceHandler如何找到指定元素的parser

我们还是接着前面的代码handler.parse(Element element, ParserContext parserContext)往下看,是不是这样吧:

父类 NamespaceHandlerSupport#parse public BeanDefinition parse(Element element, ParserContext parserContext) { //这里,继续调用了本类的另一个方法来获取Parser return findParserForElement(element, parserContext).parse(element, parserContext); } // 这里就是上面调用的方法,来获取Parser private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); // 这里的parser是一个map,map的元素就是来自于子类的init方法 BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }

这两个方法是在父类中实现的,整体来说,NamespaceHandlerSupport中维护了一个map,里面保存本namespace下,具体的元素及其对应的parser。

/** * Stores the {@link BeanDefinitionParser} implementations keyed by the * local name of the {@link Element Elements} they handle. */ private final Map<String, BeanDefinitionParser> parsers = new HashMap<String, BeanDefinitionParser>();

我们看看,这个parser是什么时候存了东西进去的吧?通过find usage,发现如下方法会进行put操作:

NamespaceHandlerSupport#registerBeanDefinitionParser protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { this.parsers.put(elementName, parser); }

这个方法还比较熟悉,因为在前面出现过了:

public class UtilNamespaceHandler extends NamespaceHandlerSupport { private static final String SCOPE_ATTRIBUTE = "scope"; // 这个init方法,就是在之前通过namespaceUri来获取对应的handler时,初始化的 @override public void init() { registerBeanDefinitionParser("constant", new ConstantBeanDefinitionParser()); registerBeanDefinitionParser("property-path", new PropertyPathBeanDefinitionParser()); registerBeanDefinitionParser("list", new ListBeanDefinitionParser()); registerBeanDefinitionParser("set", new SetBeanDefinitionParser()); registerBeanDefinitionParser("map", new MapBeanDefinitionParser()); registerBeanDefinitionParser("properties", new PropertiesBeanDefinitionParser()); } parser实现类概述

通过上一节的讲解,我们知道了UtilNamespaceHandler下的元素,及其对应的Parser。我们看看其类图(图小,可在单独tab查看):

曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfszg.html