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

xiaoxiao2021-02-28  115

上一篇博客 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.xsd http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsd http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd http\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsd http\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop-4.3.xsd 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)方法中会选择使用默认命名空间还是使用非默认命名空间进行处理。

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/aop String namespaceUri = getNamespaceURI(ele); //根据命名空间找到命名空间处理类AopNamespaceHandler NamespaceHandler 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 { @Override public 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.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } }

转载请注明原文地址: https://www.6miu.com/read-23719.html

最新回复(0)