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

https://blog.csdn.net/qq924862077/article/details/72887698


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

Spring提供的NamespaceHandler处理器:


NamespaceHandler提供的接口方法:

[java]  view plain  copy
  1. public interface NamespaceHandler {  
  2.   
  3.   
  4.     void init();  
  5.   
  6.     BeanDefinition parse(Element element, ParserContext parserContext);  
  7.   
  8.     BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);  
  9.   
  10. }  
接下来我们介绍一下AopNamespaceHandler来对命名空间处理器做一个了解。

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

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.  <span style="color:#ff0000;">xmlns:aop="http://www.springframework.org/schema/aop"</span>  
  5.  xmlns:context="http://www.springframework.org/schema/context"  
  6.  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.   <span style="color:#ff0000;">http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd</span>  
  8.   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标签解析文件的关系。

[html]  view plain  copy
  1. http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd  
  2. http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd  
  3. http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd  
  4. http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd  
  5. http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsd  
  6. http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd  
  7. http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd  
  8. http\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsd  
  9. http\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop-4.3.xsd  
  10. http\://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)方法中会选择使用默认命名空间还是使用非默认命名空间进行处理。

[java]  view plain  copy
  1. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {  
  2.         if (delegate.isDefaultNamespace(root.getNamespaceURI())) {  
  3.             NodeList nl = root.getChildNodes();  
  4.             for (int i = 0; i < nl.getLength(); i++) {  
  5.                 Node node = nl.item(i);  
  6.                 if (node instanceof Element) {  
  7.                     Element ele = (Element) node;  
  8.                     String namespaceUri = ele.getNamespaceURI();  
  9.                     if (delegate.isDefaultNamespace(namespaceUri)) {  
  10.                         //这里讲将对默认命名空间(http://www.springframework.org/schema/beans)下的标签节点(bean、import、alias等)进行处理  
  11.                         parseDefaultElement(ele, delegate);  
  12.                     }  
  13.                     else {  
  14.                         //这里对非默认命名空间下的标签进行处理  
  15.                         delegate.parseCustomElement(ele);  
  16.                     }  
  17.                 }  
  18.             }  
  19.         }  
  20.         else {  
  21.             delegate.parseCustomElement(root);  
  22.         }  
  23.     }  
在BeanDefinitionParserDelegate的parseCustomElement中会进行选择NamespaceHandler进行配置文件解析处理。

[java]  view plain  copy
  1. public BeanDefinition parseCustomElement(Element ele) {  
  2.         return parseCustomElement(ele, null);  
  3.     }  
  4.     public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {  
  5.         //获取xml配置文件中的命名空间http://www.springframework.org/schema/aop  
  6.         String namespaceUri = getNamespaceURI(ele);  
  7.         //根据命名空间找到命名空间处理类AopNamespaceHandler  
  8.         NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);  
  9.         if (handler == null) {  
  10.             error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);  
  11.             return null;  
  12.         }  
  13.         //解析命名空间支持的标签  
  14.         return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));  
  15.     }  

在AopNamespaceHandler中会看到其初始化定义的标签解析处理器。接下来进行的操作就是对标签进行解析处理最终生成BeanDefinition
[java]  view plain  copy
  1. public class AopNamespaceHandler extends NamespaceHandlerSupport {  
  2.   
  3.     @Override  
  4.     public void init() {  
  5.         // In 2.0 XSD as well as in 2.1 XSD.  
  6.         registerBeanDefinitionParser("config"new ConfigBeanDefinitionParser());  
  7.         registerBeanDefinitionParser("aspectj-autoproxy"new AspectJAutoProxyBeanDefinitionParser());  
  8.         registerBeanDefinitionDecorator("scoped-proxy"new ScopedProxyBeanDefinitionDecorator());  
  9.   
  10.         // Only in 2.0 XSD: moved to context namespace as of 2.1  
  11.         registerBeanDefinitionParser("spring-configured"new SpringConfiguredBeanDefinitionParser());  
  12.     }  
  13.   
  14. }  

猜你喜欢

转载自blog.csdn.net/lppl010_/article/details/80188656