Spring-标签-默认标签bean-自定义标签的解析

完成了默认标签的接信息之后,返回来再看processBeanDefinition方法,除了默认的标签之外,还有自定义标签
DefaultBeanDefinitionDocumentReader.java中processBeanDefinition方法

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

}

由之前的分析可知,parseBeanDefinitionElement是对默认的标签进行解析,decorateBeanDefinitionIfRequired(ele,bdholder);则是对自定义的标签进行解析:

< bean id=”test” class=”test.MyClass”>
   


当Spring中的bean使用的是默认的标签配置,但是其子元素使用了自定义的配置,那么就会执行decorateBeanDefinitionIfRequired方法,

  public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return this.decorateBeanDefinitionIfRequired(ele, definitionHolder, (BeanDefinition)null);
    }

decorateBeanDefinitionIfRequired方法的第三个参数设置为空,这个参数是父类bean,当对某个嵌套配置进行分析时,这里需要传递父类beanDefinition,分析源码得知这里传递的参数是为了使用父类的scope属性,以备若子类没有设置scope时默认使用父类的属性,首先调用时时顶层配置,所以传递为空:

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
        BeanDefinitionHolder finalDefinition = definitionHolder;
        NamedNodeMap attributes = ele.getAttributes();
        //遍历所有的属性,查看是否有适用于修饰的子元素
        for(int i = 0; i < attributes.getLength(); ++i) {
            Node node = attributes.item(i);
            finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
        }

        NodeList children = ele.getChildNodes();
        //遍历所有的子节点,是否有适用于修饰的子元素
        for(int i = 0; i < children.getLength(); ++i) {
            Node node = children.item(i);
            if (node.getNodeType() == 1) {
                finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
            }
        }

        return finalDefinition;
    }

由decorateBeanDefinitionIfRequired方法可知,当该方法遍历到元素属性或者子节点有自定义属性时,调用decorateIfRequired方法

public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
        //获取自定义标签的命名空间
        String namespaceUri = this.getNamespaceURI(node);
        //对非默认标签进行修饰
        if (!this.isDefaultNamespace(namespaceUri)) {
             //根据命名标签找到对应的处理器,进行修饰
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler != null) {
                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
            }

            if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
                this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
            }
        }

        return originalDef;
    }

上述方法,首先是获取属性或者元素的命名空间,来判断该元素或者该属性是否适用于自定义标签的解析条件,找出来自定义类型所对应的NamespaceHandler进行进一步的解析,在该方法中对于默认的标签处理是直接略过的,因为默认的标签到这步已经被处理完了,这里只处理bean的自定义标签和属性进行处理。

你可能感兴趣的:(Java,Spring)