Skip to content

Latest commit

 

History

History
646 lines (534 loc) · 23 KB

Spring-Custom-label-resolution.md

File metadata and controls

646 lines (534 loc) · 23 KB

Spring 自定义标签解析

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-Spring
  • 与自定义标签解析相关的类
    1. org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
    2. org.springframework.beans.factory.xml.NamespaceHandlerSupport
  • 开始源码之前先搭建一个环境

环境搭建

  • 创建对象
publicclassUserXtd { privateStringuserName; privateStringemailAddress; publicStringgetUserName() { returnuserName; } publicvoidsetUserName(StringuserName) { this.userName = userName; } publicStringgetEmailAddress() { returnemailAddress; } publicvoidsetEmailAddress(StringemailAddress) { this.emailAddress = emailAddress; } }
  • 创建 xsd 文件
<?xml version="1.0" encoding="UTF-8" ?> <schemaxmlns="http://www.w3.org/2001/XMLSchema"targetNamespace="http://www.huifer.com/schema/user"elementFormDefault="qualified"> <elementname="myUser"> <complexType> <attributename="id"type="string"/> <attributename="userName"type="string"/> <attributename="emailAddress"type="string"/> </complexType> </element> </schema>
  • 创建 namespaceHandler
publicclassUserNamespaceHandlerextendsNamespaceHandlerSupport { @Overridepublicvoidinit() { registerBeanDefinitionParser("myUser", newUserBeanDefinitionParser()); } }
  • 创建 beanDefinitionParser
publicclassUserBeanDefinitionParserextendsAbstractSingleBeanDefinitionParser { /** * 标签对应class * @param element the {@code Element} that is being parsed * @return */@OverrideprotectedClass<?> getBeanClass(Elementelement) { returnUserXtd.class; } @OverrideprotectedvoiddoParse(Elementelement, ParserContextparserContext, BeanDefinitionBuilderbuilder) { // 获取 userName 标签属性值Stringname = element.getAttribute("userName"); // 获取 emailAddress 标签属性值Stringaddress = element.getAttribute("emailAddress"); if (StringUtils.hasText(name)) { builder.addPropertyValue("userName", name); } if (StringUtils.hasText(address)) { builder.addPropertyValue("emailAddress", address); } } }
  • 创建 resource/META-INF/spring.handlers
http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler 
  • 创建 resource/META-INF/spring.schemas
http\://www.huifer.com/schema/user.xsd=META-INF/spring-test.xsd 
  • 创建测试用例 xml
<?xml version="1.0" encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:myname="http://www.huifer.com/schema/user"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.huifer.com/schema/user http://www.huifer.com/schema/user.xsd"> <myname:myUserid="testUserBean"userName="huifer"emailAddress="huifer97@163.com"/> </beans>
  • 创建 Java 运行方法
/** * 自定义标签测试用例 */publicclassXSDDemo { publicstaticvoidmain(String[] args) { ApplicationContextapplicationContext = newClassPathXmlApplicationContext("XTD-xml.xml"); UserXtduser = (UserXtd) applicationContext.getBean("testUserBean"); System.out.println(user.getEmailAddress()); } }
  • 这里我们希望输出结果是huifer97@163.com,运行后结果也确实是huifer97@163.com

解析 DefaultNamespaceHandlerResolver

  • 入口方法org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions
protectedvoidparseBeanDefinitions(Elementroot, BeanDefinitionParserDelegatedelegate) { if (delegate.isDefaultNamespace(root)) { NodeListnl = root.getChildNodes(); for (inti = 0; i < nl.getLength(); i++) { Nodenode = nl.item(i); if (nodeinstanceofElement) { Elementele = (Element) node; if (delegate.isDefaultNamespace(ele)) { // 不同标签的解析parseDefaultElement(ele, delegate); } else { // 非spring 默认标签解析delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
  • 调用链路
  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element)
    • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
/** * Parse a custom element (outside of the default namespace). * <p> * 自定义标签解析 * * @param ele the element to parse * @param containingBd the containing bean definition (if any) * @return the resulting bean definition */@NullablepublicBeanDefinitionparseCustomElement(Elementele, @NullableBeanDefinitioncontainingBd) { // 自定义标签解析StringnamespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { returnnull; } // 根据命名空间获取处理类NamespaceHandlerhandler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); returnnull; } // 自定义处理器returnhandler.parse(ele, newParserContext(this.readerContext, this, containingBd)); }

image-20200109084131415

  • http://www.huifer.com/schema/user和我们定义的 xsd 文件中的 url 相同,如何找到对应的 NamespaceHandler,在META-INF/spring.handlers中有定义,

    http\://www.huifer.com/schema/user=com.huifer.source.spring.parser.UserNamespaceHandler

    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);这行代码就是获取spring.handlers中的定义

  • 处理方法org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve

/** * Locate the {@link NamespaceHandler} for the supplied namespace URI * from the configured mappings. * * 根据 namespaceUri 获取对应的 {@link NamespaceHandler} * @param namespaceUri the relevant namespace URI * @return the located {@link NamespaceHandler}, or {@code null} if none found */@Override@NullablepublicNamespaceHandlerresolve(StringnamespaceUri) { // 获取handlerMappingMap<String, Object> handlerMappings = getHandlerMappings(); // 从 handlerMapping 中获取类名ObjecthandlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { returnnull; } // 判断是否处理过,处理过直接返回elseif (handlerOrClassNameinstanceofNamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { // 没有处理,进行反射还原类StringclassName = (String) handlerOrClassName; try { // 通过反射还原类Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { thrownewFatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } // 初始化类NamespaceHandlernamespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); // 调用init()方法,自定义类中实现namespaceHandler.init(); // 放入缓存handlerMappings.put(namespaceUri, namespaceHandler); // 返回自定义的 namespaceHandlerreturnnamespaceHandler; } catch (ClassNotFoundExceptionex) { thrownewFatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageErrorerr) { thrownewFatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } }
  • org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings跟踪这个方法
/** * Load the specified NamespaceHandler mappings lazily. * * 获取handlerMappings */privateMap<String, Object> getHandlerMappings() { Map<String, Object> handlerMappings = this.handlerMappings; }

image-20200109085606240

  • 这里直接存在数据了,他是从什么时候加载的?

  • org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

    这个方法在注册 bean 定义的时候调用

    publicintregisterBeanDefinitions(Documentdoc, Resourceresource) throwsBeanDefinitionStoreException { BeanDefinitionDocumentReaderdocumentReader = createBeanDefinitionDocumentReader(); intcountBefore = getRegistry().getBeanDefinitionCount(); // 注册方法// createReaderContext 初始化HandlerMappingdocumentReader.registerBeanDefinitions(doc, createReaderContext(resource)); returngetRegistry().getBeanDefinitionCount() - countBefore; }
  • 继续跟踪createReaderContext

    org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext
    publicXmlReaderContextcreateReaderContext(Resourceresource) { returnnewXmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, getNamespaceHandlerResolver()); }
  • 继续跟踪getNamespaceHandlerResolver

    org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getNamespaceHandlerResolver

    publicNamespaceHandlerResolvergetNamespaceHandlerResolver() { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } returnthis.namespaceHandlerResolver; }
  • 继续跟踪createDefaultNamespaceHandlerResolver

    org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver

    protectedNamespaceHandlerResolvercreateDefaultNamespaceHandlerResolver() { ClassLoadercl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); returnnewDefaultNamespaceHandlerResolver(cl); }
  • 继续跟踪DefaultNamespaceHandlerResolver

    org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver

    publicDefaultNamespaceHandlerResolver(@NullableClassLoaderclassLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); }

    他回到了我们之前疑问的地方 handlerMappings 如何出现的

    断点

    image-20200109090456547

    publicDefaultNamespaceHandlerResolver(@NullableClassLoaderclassLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); }

    public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";

    image-20200109090655157

    此时还是空

    走完

    image-20200109091216505

    @OverridepublicStringtoString() { return"NamespaceHandlerResolver using mappings " + getHandlerMappings(); }
/** * Load the specified NamespaceHandler mappings lazily. * * 获取handlerMappings */privateMap<String, Object> getHandlerMappings() { Map<String, Object> handlerMappings = this.handlerMappings; // 缓存不存在if (handlerMappings == null) { synchronized (this) { handlerMappings = this.handlerMappings; if (handlerMappings == null) { if (logger.isTraceEnabled()) { logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); } try { // 将本地文件读出Propertiesmappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } handlerMappings = newConcurrentHashMap<>(mappings.size()); // 转换成map结构CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOExceptionex) { thrownewIllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } returnhandlerMappings; }

image-20200109094032421

org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve

@Override@NullablepublicNamespaceHandlerresolve(StringnamespaceUri) { // 获取handlerMappingMap<String, Object> handlerMappings = getHandlerMappings(); // 从 handlerMapping 中获取类名ObjecthandlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { returnnull; } // 判断是否处理过,处理过直接返回elseif (handlerOrClassNameinstanceofNamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { // 没有处理,进行反射还原类StringclassName = (String) handlerOrClassName; try { // 通过反射还原类Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { thrownewFatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } // 初始化类NamespaceHandlernamespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); // 调用init()方法,自定义类中实现namespaceHandler.init(); // 放入缓存handlerMappings.put(namespaceUri, namespaceHandler); // 返回自定义的 namespaceHandlerreturnnamespaceHandler; } catch (ClassNotFoundExceptionex) { thrownewFatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageErrorerr) { thrownewFatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } }

执行init方法

publicclassUserNamespaceHandlerextendsNamespaceHandlerSupport { @Overridepublicvoidinit() { registerBeanDefinitionParser("myUser", newUserBeanDefinitionParser()); } }
/** * Subclasses can call this to register the supplied {@link BeanDefinitionParser} to * handle the specified element. The element name is the local (non-namespace qualified) * name. * * 将标签名称,标签解析类放入 */protectedfinalvoidregisterBeanDefinitionParser(StringelementName, BeanDefinitionParserparser) { this.parsers.put(elementName, parser); }
  • 方法走完,回到开始的方法

    /** * Parse a custom element (outside of the default namespace). * <p> * 自定义标签解析 * * @param ele the element to parse * @param containingBd the containing bean definition (if any) * @return the resulting bean definition */@NullablepublicBeanDefinitionparseCustomElement(Elementele, @NullableBeanDefinitioncontainingBd) { // 自定义标签解析StringnamespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { returnnull; } // 根据命名空间获取处理类// org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolveNamespaceHandlerhandler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); returnnull; } // 自定义处理器returnhandler.parse(ele, newParserContext(this.readerContext, this, containingBd)); }

image-20200109092801572

org.springframework.beans.factory.xml.NamespaceHandler#parse

  • org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse

    @Override@NullablepublicBeanDefinitionparse(Elementelement, ParserContextparserContext) { BeanDefinitionParserparser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }

org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement

@NullableprivateBeanDefinitionParserfindParserForElement(Elementelement, ParserContextparserContext) { // 获取标签名称StringlocalName = parserContext.getDelegate().getLocalName(element); // 在map中获取对应的标签解析类BeanDefinitionParserparser = this.parsers.get(localName); // 空报错if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } // 不为空返回returnparser; }

image-20200109093242494

org.springframework.beans.factory.xml.BeanDefinitionParser#parse

  • org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse
publicfinalBeanDefinitionparse(Elementelement, ParserContextparserContext) { /** * {@link AbstractSingleBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)} */AbstractBeanDefinitiondefinition = parseInternal(element, parserContext); }

org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal

@OverrideprotectedfinalAbstractBeanDefinitionparseInternal(Elementelement, ParserContextparserContext) { BeanDefinitionBuilderbuilder = BeanDefinitionBuilder.genericBeanDefinition(); StringparentName = getParentName(element); if (parentName != null) { builder.getRawBeanDefinition().setParentName(parentName); } // 调用自己实现的方法 com.huifer.source.spring.parser.UserBeanDefinitionParser.getBeanClassClass<?> beanClass = getBeanClass(element); if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); } else { // getBeanClassName 同样也是可以在自定义的解析类中实现StringbeanClassName = getBeanClassName(element); if (beanClassName != null) { builder.getRawBeanDefinition().setBeanClassName(beanClassName); } } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); BeanDefinitioncontainingBd = parserContext.getContainingBeanDefinition(); if (containingBd != null) { // Inner bean definition must receive same scope as containing bean.// 设置scopebuilder.setScope(containingBd.getScope()); } if (parserContext.isDefaultLazyInit()) { // Default-lazy-init applies to custom bean definitions as well.// 设置 lazy-initbuilder.setLazyInit(true); } // 执行解析方法,在自定义解析类中存在com.huifer.source.spring.parser.UserBeanDefinitionParser.doParsedoParse(element, parserContext, builder); returnbuilder.getBeanDefinition(); }

image-20200109094654409

执行com.huifer.source.spring.parser.UserBeanDefinitionParser#doParse

@OverrideprotectedvoiddoParse(Elementelement, ParserContextparserContext, BeanDefinitionBuilderbuilder) { // 获取 userName 标签属性值Stringname = element.getAttribute("userName"); // 获取 emailAddress 标签属性值Stringaddress = element.getAttribute("emailAddress"); if (StringUtils.hasText(name)) { builder.addPropertyValue("userName", name); } if (StringUtils.hasText(address)) { builder.addPropertyValue("emailAddress", address); } }
close