栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring中的可扩展点(一)自定义标签

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring中的可扩展点(一)自定义标签

目录

1.自定义标签具体步骤

2.DEMO例程

2.1 创建User类

2.2 创建自定义解析器UserBeanDefinitionParser

2.3 创建自定义处理器UserNameSpaceHandler

2.4 创建自定义XSD

2.5 创建Spring.handlers 和 Spring.schemas

2.6 测试类 Application

2.7 运行结果及目录结构:

​3.我们创建的几个文件是如何关联到一起的

4.Spring是如何做到可扩展的


1.自定义标签具体步骤
  1. 创建一个需要被自定义标签解析的bean
  2. 创建一个标签解析器Parser,继承自 AbstractSingleBeanDefinitionParser ,用来解析 XSD 中的标签。
  3. 创建一个标签处理器Handler,继承自 NamespaceHandlerSupport, 并实现其init()方法
  4. 创建一个自定义的 XSD 描述文件
  5. 编写 Spring.handlers 和 Spring.schemas 文件,用于引导spring加载对应标签处理器

2.DEMO例程

2.1 创建User类
package com.zoo.customXsd;


public class User {
	private String userName;
	private String passWord;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassWord() {
		return passWord;
	}

	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}

	@Override
	public String toString() {
		return "User{" +
				"userName='" + userName + ''' +
				", passWord='" + passWord + ''' +
				'}';
	}
}

2.2 创建自定义解析器UserBeanDefinitionParser
package com.zoo.customXsd;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;


public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

	@Override
	protected Class getBeanClass(Element element) {
		return User.class;
	}

	@Override
	protected void doParse(Element element, BeanDefinitionBuilder builder) {
		String userName = element.getAttribute("userName");
		String passWord = element.getAttribute("passWord");

		if(StringUtils.hasText(userName)){
			builder.addPropertyValue("userName",userName);
		}

		if(StringUtils.hasText(passWord)){
			builder.addPropertyValue("passWord",passWord);
		}
	}
}

2.3 创建自定义处理器UserNameSpaceHandler
package com.zoo.customXsd;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;


public class UserNameSpaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("user",new UserBeanDefinitionParser());
	}
}

2.4 创建自定义XSD



	
		
			
				
					
					
					
				
			
		
	

2.5 创建Spring.handlers 和 Spring.schemas

Spring.schemas:

http://www.en.com/schema/user.xsd=META-INF/user.xsd

Spring.handlers:

http://www.en.com/schema/user=com.zoo.customXsd.UserNameSpaceHandler

2.6 测试类 Application
package com.zoo;

import com.zoo.customXsd.User;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Application {
	public static void main(String[] args) {

		AbstractApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		User user = (User)ac.getBean("user");
		System.out.println(user);
		ac.registerShutdownHook();
	}
}



2.7 运行结果及目录结构:

3.我们创建的几个文件是如何关联到一起的

        首先Spring.schemas做了一个版本与本地xsd文件的映射,作用是让Spring优先加载本地xsd文件(毕竟我们写的user.xsd网络上访问不了)。其次Spring.handlers文件中配置了xsd命名空间与对应的处理器的匹配关系,让UserNameSpaceHandler和user.xsd关联到了一起。最后UserNameSpaceHandler代码内部绑定了和UserBeanDefinitionParser的关系。

4.Spring是如何做到可扩展的

        Spring.schemas关联关系配置在AbstractXmlApplicationContext#loadBeanDefinitions()方法:

        一系列的构造函数跟进去,发现在此处配置了PluggableSchemaResolver和spring.schemas的映射关系:

具体调用堆栈:

:63, DelegatingEntityResolver (org.springframework.beans.factory.xml)
:68, ResourceEntityResolver (org.springframework.beans.factory.xml)
loadBeanDefinitions:93, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:137, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:674, AbstractApplicationContext (org.springframework.context.support)
refresh:534, AbstractApplicationContext (org.springframework.context.support)
:145, ClassPathXmlApplicationContext (org.springframework.context.support)
:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:13, Application (com.zoo)

        spring.schemas文件信息的读取在PluggableSchemaResolver#getSchemaMappings(): 

具体调用堆栈:

getSchemaMappings:149, PluggableSchemaResolver (org.springframework.beans.factory.xml)
resolveEntity:116, PluggableSchemaResolver (org.springframework.beans.factory.xml)
resolveEntity:90, DelegatingEntityResolver (org.springframework.beans.factory.xml)
resolveEntity:78, ResourceEntityResolver (org.springframework.beans.factory.xml)
resolveEntity:110, EntityResolverWrapper (com.sun.org.apache.xerces.internal.util)
resolveEntity:1079, XMLEntityManager (com.sun.org.apache.xerces.internal.impl)
resolveDocument:655, XMLSchemaLoader (com.sun.org.apache.xerces.internal.impl.xs)
findSchemaGrammar:2681, XMLSchemaValidator (com.sun.org.apache.xerces.internal.impl.xs)
handleStartElement:2056, XMLSchemaValidator (com.sun.org.apache.xerces.internal.impl.xs)
startElement:816, XMLSchemaValidator (com.sun.org.apache.xerces.internal.impl.xs)
scanStartElement:375, XMLNSDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
scanRootElementHook:614, XMLNSDocumentScannerImpl$NSContentDriver (com.sun.org.apache.xerces.internal.impl)
next:3134, XMLDocumentFragmentScannerImpl$FragmentContentDriver (com.sun.org.apache.xerces.internal.impl)
next:867, XMLDocumentScannerImpl$PrologDriver (com.sun.org.apache.xerces.internal.impl)
next:605, XMLDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
next:113, XMLNSDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
scanDocument:507, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
parse:867, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:796, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:142, XMLParser (com.sun.org.apache.xerces.internal.parsers)
parse:247, DOMParser (com.sun.org.apache.xerces.internal.parsers)
parse:339, DocumentBuilderImpl (com.sun.org.apache.xerces.internal.jaxp)
loadDocument:77, DefaultDocumentLoader (org.springframework.beans.factory.xml)
doLoadDocument:432, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:390, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:338, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:188, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:224, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:195, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:257, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:134, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:98, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:137, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:674, AbstractApplicationContext (org.springframework.context.support)
refresh:534, AbstractApplicationContext (org.springframework.context.support)
:145, ClassPathXmlApplicationContext (org.springframework.context.support)
:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:13, Application (com.zoo)

        Spring.handlers配置关系在XmlBeanDefinitionReader#registerBeanDefinitions():

        一系列构造函数跟进去,发现在DefaultNamespaceHandlerResolver类配置了和Spring.handlers文件的对应关系:

具体调用堆栈:

:93, DefaultNamespaceHandlerResolver (org.springframework.beans.factory.xml)
createDefaultNamespaceHandlerResolver:552, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
getNamespaceHandlerResolver:540, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
createReaderContext:531, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:512, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:338, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:188, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:224, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:195, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:257, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:134, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:98, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:137, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:674, AbstractApplicationContext (org.springframework.context.support)
refresh:534, AbstractApplicationContext (org.springframework.context.support)
:145, ClassPathXmlApplicationContext (org.springframework.context.support)
:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:13, Application (com.zoo)

        Spring.handlers的读取在DefaultNamespaceHandlerResolver#getHandlerMappings():

具体堆栈:

getHandlerMappings:158, DefaultNamespaceHandlerResolver (org.springframework.beans.factory.xml)
resolve:119, DefaultNamespaceHandlerResolver (org.springframework.beans.factory.xml)
parseCustomElement:1400, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseCustomElement:1384, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseBeanDefinitions:179, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
doRegisterBeanDefinitions:149, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:96, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:512, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:338, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:188, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:224, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:195, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:257, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:134, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:98, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:137, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:674, AbstractApplicationContext (org.springframework.context.support)
refresh:534, AbstractApplicationContext (org.springframework.context.support)
:145, ClassPathXmlApplicationContext (org.springframework.context.support)
:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:13, Application (com.zoo)

        配置文件读取完毕,就是最后的标签解析工作了,入口在DefaultBeanDefinitionDocumentReader#parseBeanDefinitions()方法:

        继续跟进到BeanDefinitionParserDelegate#parseCustomElement()方法:

        这里我们可以看到已经可以拿到我们自定义的handler了,跟进这个resolve方法:


        可以看到红框对UserNameSpaceHandler进行了一个反射创建,然后蓝框里调用了UserNameSpaceHandler的init()方法,将UserBeanDefinitionParser注册到了UserNameSpaceHandler中,最后绿框将命名空间和对应的handler对应上。

        创建好UserNameSpaceHandler的实例后,可以看到调用了UserNameSpaceHandler的parse方法,然后经过一系列拥有继承关系的parse方法,最终会调用到我们自定义的UserBeanDefinitionParser解析器的parse方法中,从而完成对自定义标签的解析。

具体调用过程:

doParse:21, UserBeanDefinitionParser (com.zoo.customXsd)
doParse:146, AbstractSingleBeanDefinitionParser (org.springframework.beans.factory.xml)
parseInternal:88, AbstractSingleBeanDefinitionParser (org.springframework.beans.factory.xml)
parse:63, AbstractBeanDefinitionParser (org.springframework.beans.factory.xml)
parse:74, NamespaceHandlerSupport (org.springframework.beans.factory.xml)
parseCustomElement:1405, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseCustomElement:1384, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseBeanDefinitions:179, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
doRegisterBeanDefinitions:149, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:96, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:512, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:338, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:188, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:224, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:195, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:257, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:134, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:98, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:137, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:674, AbstractApplicationContext (org.springframework.context.support)
refresh:534, AbstractApplicationContext (org.springframework.context.support)
:145, ClassPathXmlApplicationContext (org.springframework.context.support)
:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:13, Application (com.zoo)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/880973.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号