Spring源码解析--Spring配置文件解析NamespaceHandler(五)

来源:互联网 发布:mac电脑性能在线测试 编辑:程序博客网 时间:2024/06/14 23:34

上一篇博客 Spring源码解析--Spring配置文件解析BeanDefinitionParserDelegate(四)中我们介绍了对Bean基本元素的解析处理器,接下来我们介绍一下Spring提供的NamespaceHandler的处理机制,简单来说就是命名空间处理器,Spring为了开放性提供了NamespaceHandler机制,这样我们就可以根据需求自己来处理我们设置的标签元素。

Spring提供的NamespaceHandler处理器:


NamespaceHandler提供的接口方法:

public interface NamespaceHandler {void init();BeanDefinition parse(Element element, ParserContext parserContext);BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);}
接下来我们介绍一下AopNamespaceHandler来对命名空间处理器做一个了解。

我们使用基于xml的spring配置时,可能需要配置如<aop:config />这样的标签,在配置这个标签之前,通常我们需要引入这个aop所在的命名空间,红色部分。

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd />

只有通过配置aop的命名空间才会找到AOP标签的处理器AopNamespaceHandler,在AOP的jar中的spring.handlers配置文件中配置了命名空间和命名空间处理器之间的关系。

内容:

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

在spring.schemas配置文件中添加了url和本地xsd标签解析文件的关系。

http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsdhttp\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsdhttp\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsdhttp\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsdhttp\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsdhttp\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsdhttp\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsdhttp\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsdhttp\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop-4.3.xsdhttp\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.3.xsd

在jar中已经内置了xsd文件,文件内容包含了命名空间处理器AopNamespaceHandler对于标签处理的规则。

对于上述内容的理解可以参考之前的文章 Spring源码学习--自定义标签

接下来我们介绍一下选择NamespaceHandler进行配置文件解析的流程。

在DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中会选择使用默认命名空间还是使用非默认命名空间进行处理。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {        if (delegate.isDefaultNamespace(root.getNamespaceURI())) {            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;                    String namespaceUri = ele.getNamespaceURI();                    if (delegate.isDefaultNamespace(namespaceUri)) {                        //这里讲将对默认命名空间(http://www.springframework.org/schema/beans)下的标签节点(bean、import、alias等)进行处理                        parseDefaultElement(ele, delegate);                    }                    else {                        //这里对非默认命名空间下的标签进行处理                        delegate.parseCustomElement(ele);                    }                }            }        }        else {            delegate.parseCustomElement(root);        }    }
在BeanDefinitionParserDelegate的parseCustomElement中会进行选择NamespaceHandler进行配置文件解析处理。

public BeanDefinition parseCustomElement(Element ele) {return parseCustomElement(ele, null);}public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {//获取xml配置文件中的命名空间http://www.springframework.org/schema/aopString namespaceUri = getNamespaceURI(ele);//根据命名空间找到命名空间处理类AopNamespaceHandlerNamespaceHandler 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));}

在AopNamespaceHandler中会看到其初始化定义的标签解析处理器。接下来进行的操作就是对标签进行解析处理最终生成BeanDefinition
public class AopNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {// In 2.0 XSD as well as in 2.1 XSD.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());// Only in 2.0 XSD: moved to context namespace as of 2.1registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}}




阅读全文
2 0