spring自定义xml标签
来源:互联网 发布:淘宝买的散装卫生巾 编辑:程序博客网 时间:2024/06/10 04:02
spring自定义xml标签
要实现自定义的xml配置,需要有两个默认spring配置文件来支持。一个是spring.schemas,一个是spring.handlers,前者是为了验证你自定义的xml配置文件是否符合你的格式要求,后者是告诉spring该如何来解析你自定义的配置文件。
自定义标签涉及的核心接口为:
- NamespaceHandler
- BeanDefinitionParser
实际使用的时候,一般分别继承类:
- NamespaceHandlerSupport:init
- AbstractSingleBeanDefinitionParser:parse
以spring事务标签为例(前提:要了解bean注册过程):
1. 配置文件:
spring.handlers
spring.schemas
2. 调用逻辑
- 在第3步中 registerBeanDefinitions 调用 createReaderContext
//class XmlBeanDefinitionReader public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
- 第4步 createReaderContext 中调用getNamespaceHandlerResolver方法获取: NamespaceHandlerResolver
//class XmlBeanDefinitionReader public XmlReaderContext createReaderContext(Resource resource) { return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, getNamespaceHandlerResolver()); } public NamespaceHandlerResolver getNamespaceHandlerResolver() { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return this.namespaceHandlerResolver; }
new 一个 DefaultNamespaceHandlerResolver
//class XmlBeanDefinitionReader protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader()); }
DEFAULT_HANDLER_MAPPINGS_LOCATION: META-INF/spring.handlers
//DefaultNamespaceHandlerResolver public DefaultNamespaceHandlerResolver(ClassLoader classLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.handlerMappingsLocation = handlerMappingsLocation; }
DefaultNamespaceHandlerResolver的属性:private volatile Map handlerMappings保存的是
namespace URI 与 NamespaceHandler的映射
- 第5步调用DefaultBeanDefinitionDocumentReader(父类BeanDefinitionDocumentReader)的 registerBeanDefinitions 方法
//BeanDefinitionDocumentReader public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }
delegate.parseCustomElement(ele); 这一行代码是解析自定义标签
//class DefaultBeanDefinitionDocumentReader protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { 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; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
- 根据元素标签获取:NamespaceHandler,并调用其 init 方法
- 调用 NamespaceHandler 的 parse 方法,在 parse 方法里解析标签,然后返回BeanDefinition,后续会被spring注册
//class BeanDefinitionParserDelegate public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); 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)); }
3. 定制点
- 定制 init 方法:一般在init方法中注册BeanDefinitionParser, 存储在其父类NamespaceHandlerSupport的属性:parsers 中
- 定制 parse 方法:一般在parse方法中返回BeanDefinition
阅读全文
0 0
- spring自定义xml标签
- Spring自定义xml标签
- Spring下自定义xml标签
- spring源码学习之:xml配置文件标签自定义
- spring源码学习之:xml配置文件标签自定义
- spring自定义标签
- spring自定义标签实现
- spring 自定义标签 学习
- 自定义Spring配置标签
- spring自定义标签
- spring自定义标签
- spring自定义标签实现
- spring自定义标签
- Spring自定义标签解析
- spring 自定义标签
- Spring 自定义标签
- Spring自定义标签
- spring 自定义标签
- vim 通过 vbundle 安装 pyclewn 2.3(gdb调试)
- POJ 2739 Sum of Consecutive Prime Numbers
- LVITEM概述
- centos7部署lnmp心得:centos7+nginx+php+mysql+edusoho
- zabbix客户端安装(二)
- spring自定义xml标签
- if (IDCANCEL==dlg.DoModal()) { return; }解释
- MFC常用的类及其成员函数简介
- Symfony Security 机制
- xml添加下着重号样式
- RE:JAVA学习-变量,基本数据类型,Scanner
- HDU5699货物运输 (二分+不等式判断)
- python读取字符串按列分配后按行读出
- CodeForces 427D-Match & Catch