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

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

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

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

  1. 创建一个解析自定义标签的解析器,解析xml自定义标签
  2. 创建一个handler,将解析器组件注入到spring容器中
  3. 定义命名空间spring.handlers 和 spring.schemas
    spring.handlers文件中定义的是命名空间和命名空间handler的映射关系
    默认位置是/META-INF/文件夹下
  4. 创建一个需要自定义标签定义的组件(javaBean)
  5. 定义一个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.

偶尔问自己几个问题:

自定义标签解析,注册自定义的parser的时机是在什么时候?
xmlBeanDefiniationReader get Element root, parse element
BeanDefinitionDocumentReader ready to parse element.
简单地说是在开始解析自定义标签的时候,类:BeanDefinitionParserDelegate parseCustomElement.
再委托给DefaultNamespaceResolver得到具体的handler.
执行resolve过程
namespaceUri 就是http://www.springframework.org/schema/aop
1. getHandlerMappings spring.handlers
2. get handler from mapping by namespaceUri
3. 实例化
4. 执行init方法,该方法里面就实现了自定义标签和parse的映射关系
5. 存入HandlerMappings中,备用
返回namespaceHandler,
3. execute namespaceHandlerSupport parse method
4. execute custom doParse method.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值