Spring源码笔记-1.3 获取bean流程之解析bean标签中的自定义标签元素

# 本文要看啥


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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));
    }

}

前面的笔记中,我们已经走完了这个方法中的第一步,感觉第一步就走了很远,眼瞅要迷路了,但无论如何,总归是拿到了我们的bdHolder, 里面已经存放了Bean标签里面的默认的元素.

如果bdHolder不为空的话,我们可以继续往下走啦.

今天来研究下这段代码

1
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

看方法名字就大概知道,这里要做的事情就是 如果有需要的话,装饰我们刚拿到的bdHolder.

那么何为需要呢?下面这样的场景便是了

1
2
3
<bean id="test" class="test.myClass">
    <mybean:user username="aaa"/>
</bean>

这里的自定义标签和

1
2
3
<mvc:resources mapping="/img/**" location="img/"/>
<aop:config/>
<tx:advice id="transactionAdvice" transaction-manager="transactionManager"/>

并不同,这里的是在bean内的, 而mvc那种标签是在beans里面,与bean同级的

# 开始进入方法吧


这次要看的主要方法就是 decorateBeanDefinitionIfRequired

这个方法主要是拆开我们之前的bean,将其各属性和各子节点全部变为node,

然后带着每个node和之前的bd去 decorateIfRequired

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
        String namespaceUri = this.getNamespaceURI(node);
      //看看是不是默认命名空间, 如果是的话那就不用管了, 在这方法里,我们只需处理自定义的标签
        if (!this.isDefaultNamespace(namespaceUri)) {
          //拿到这个命名空间的解析器 handler
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
          //如果能找到解析器,我们就可以进入装饰方法啦
            if (handler != null) {
                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
            }
		//以下都是没找到解析器的
          //命名空间不为null,而且还以spring家的网址开头,那就报错表示找不到spring解析器
            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;
    }

具体的用handler解析node会在后面详细学习,这个就先到这吧!

前面几篇文章都长得没法看了…吸取教训 篇幅尽量不要太长了.