2.1.3.3Spring源码解析——解析默认标签中的自定义标签元素

DefaultBeanDefinitionDocumentReader.java

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            //解析完bean元素的解析
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
              //对BeanDefinitionHolder进行修饰  
            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));
        }
    }

 对我们需要对beanDefinition进行装饰,是应为可能存在例如如下场景

<bean   id="test"  class="">
  <mybean:user  username="aaa"/>
</bean>

 在配置中存在自定义的标签的时候需要进行解析

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
            Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

        BeanDefinitionHolder finalDefinition = definitionHolder;

        // Decorate based on custom attributes first.
            //遍历所有的bean的属性,看是否有需要进行修饰的标签
        NamedNodeMap attributes = ele.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++) {
            Node node = attributes.item(i);
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }

        // Decorate based on custom nested elements.
  //遍历所有的bean的子bean的属性,看是否有需要进行修饰的标签
        NodeList children = ele.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
//这里函数的第三个参数是父类bean,当对某个嵌套配置进行分析时,这里需要传递父类beanDefinition。这里传递的参数其实是为了使用父类的scope属性,以备子类若没有设置scope时默认使用父类的属性。
                finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
            }
        }
        return finalDefinition;
    }
    private BeanDefinitionHolder decorateIfRequired(
            Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
//获取自定义的命名控件
        String namespaceUri = getNamespaceURI(node);
//根据命名URI获取对应的Hander的字节码路径并创建Hadnder对象进行处理
        if (!isDefaultNamespace(namespaceUri)) {
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler != null) {
                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
            }
            else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            }
            else {
                // A custom namespace, not to be handled by Spring - maybe "xml:...".
                if (logger.isDebugEnabled()) {
                    logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
                }
            }
        }
        return originalDef;
    }

 首先获取属性或者元素的命名空间,以此来判断该元素或者属性是否适用于自定义标签的解析条件,找出自定义类型所对应的NamespaceHandler并进行进一步解析。
在decorateBeanDefinitionIfRequired方法中,我们可以看到对于程序默认的标签的处理其实是直接略过的,因为默认的标签到这里已经被处理完了,这里只对自定义的标签或者说对bean的自定义属性感兴趣。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值