首页 > 程序开发 > 软件开发 > Java >

spring 源码探索--xml的自定义标签解析

2016-11-22

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate isDefaultNamespace(root)) { NodeList nl =

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            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;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

parseCustomElement

获取命名空间 通过命名空间找到对应的handler处理器 使用解析器BeanDefinitionParser解析自定义标签

如果想在spring中实现自定义标签的功能。

创建一个解析自定义标签的解析器,解析xml自定义标签 创建一个handler,将解析器组件注入到spring容器中 定义命名空间spring.handlers 和 spring.schemas
spring.handlers文件中定义的是命名空间和命名空间handler的映射关系
默认位置是/META-INF/文件夹下 创建一个需要自定义标签定义的组件(javaBean) 定义一个XSD文件描述组件的内容
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        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));
    }

get namespaceUri
使用默认的Node实现

get namespaceHandler
首先获取所有的handlerMappings,默认是META-INF/Spring.handlers
获得指定handler,init。
找到自定义标签的handler,执行init方法,
再调用NamespaceHandlerSupport的registerBeanDefinitionParser(elementName,BeanDefinitionParser)把自定义命名空间和解析器连接起来。

String className = (String) handlerOrClassName;
Class handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
            "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;

找到对应的parser进行解析
AbstractBeanDefinitionParser 中调用parse方法进行解析,再调用parseInternal得到AbstractBeanDefinition,这里面会调用到用户自定义的解析器的doParse,这个接口是继承的抽象类AbstractSingleBeanDefinitionParser的。

注册beanDefinition

有需要的话,通知监听器事件fireEvent.
相关文章
最新文章
热点推荐