步骤1:创建User
实体
步骤2:定义一个XSD
文件描述组件内容
步骤3:创建BeanDefinitionParser
接口的实现类,用来解析XSD文件中的定义和组件定义。
步骤4:创建NamespaceHandlerSupport
实现类,目的是将组件注册到Spring容器中。
步骤5:编写spring.handlers
和spring.schemas
文件,默认位置是/META-INF
目录下
步骤6:在配置文件oldbean.xml
中引入对应的命名空间以及XSD之后,就可以配置<myname:user ... />
了
步骤7:进行测试
在第2讲中,我们已经介绍了关于默认标签的解析过程。那么我们还是需要将视角在回到parseBeanDefinitions(...)
方法上来,从下图源码截图中我们可以看出来,我们首先是来判断root
和root的子节点
是否是默认表空间,即:通过delegate.isDefaultNamespace(...)
来进行判断:
【如果是默认表空间】执行
默认标签
解析——delegate.parseDefaultElement(ele, delegate);
【如果不是默认表空间】则执行自定义标签
解析——delegate.parseCustomElement(ele);
下面我们来看一下parseCustomElement(...)
方法的具体实现,具体来说有如下3个步骤:
【首先】获得
namespaceUri
,此处是通过org.w3c.dom.Node中的getNamespaceURI()�
方法进行获取的;
【其次】获得解析该自定义标签的NamespaceHandler
实现类。
【最后】调用该实现类的parse(...)
方法进行解析操作。
此方法是用于获得namespaceUri,此处是通过org.w3c.dom.Node中的getNamespaceURI()
方法进行获取的,以使用示例中为例,将会返回的**namespaceUri=“www.muse.com/schema/user…
此方法是用来获得解析该自定义标签的NamespaceHandler实现类,为下图中红框处代码:
在此处的this.readerContext.getNamespaceHandlerResolver()
方法中,实际会返回DefaultNamespaceHandlerResolver实例对象。
上面我们了解了DefaultNamespaceHandlerResolver实例对象的创建过程之后,那么下面我们就来分析一下它的resolve(namespaceUri)
这个方法的内部实现,下面是该方法的源码部分:
在getHandlerMappings()
方法中,我们获得了系统加载的所有NamespaceHandler
实例对象的映射,映射关系为:key=uri,value=NamespaceHandler实现类。但是,如果我们发现加载的handlerMappings等于null
,那么我们就需要去加载META-INF/spring.handlers
文件中的配置信息,将其生成NamespaceHandler
实例对象的映射。所以,综上所示,getHandlerMappings()
方法的主要功能就是读取spring.handlers
的配置文件并将配置文件缓存在map中。
那么以我们的演示例子来说,handlerMappings
中是包含了11个xxxNamespaceHander
实例对象的映射关系的,在下图中,红框部分就是我们自定义的UserNamespaceHandler
。
那么在调用 namespaceHandler.init() 方法的时候,其实调用的是UserNamespaceHandler
实例的init()
方法,该方法是我们自己实现的。如下图所示:
当我们调用 handlerMappings.put(namespaceUri, namespaceHandler) 方法时,那么就将原本String类型的value值“com.muse.springbootdemo.UserNamespaceHandler
”,替换为UserNamespaceHandler
实例对象了。如下图所示:
下面我们再来看一下的parse(...)
方法,该方法是用来进行自定义标签的解析操作。
在parse(...)
方法中我们可以看到,首先是通过findParserForElement(element, parserContext)
方法来找到localName对应的解析器。以我们上面的示例为例,我们在oldbean.xml中配置的是<myname:user id="user" name="muse" email="[email protected]"/>
,那么获得了localName
就等于“user”。由于我们在UserNamespaceHandler
类中已经配置了user与UserBeanDefinitionParser实例对象的对应关系,所以parser
就拿它作为方法的返回值。具体详情,请见下图所示:
在上面的代码逻辑中,我们已经获得到了parser
示例对象(UserBeanDefinitionParser
实例对象),那么我们通过调用parser对象的 parser(element, parserContext) 方法对自定义标签执行解析操作。下面是该方法涉及的源码部分:
我们在上面可以看到,对自定义标签进行解析是在parseInternal(element, parserContext)
方法中执行的,
在doParse(element, parserContext, builder)
方法中,执行了真正的自定义标签解析逻辑,那么既然是自定义标签,是无法通过Spring进行解析的,而是需要我们自己提供自定义解析类XxxBeanDefinitionParser
来实现doParse(...)
方法的,具体如下所示:
文章浏览阅读6.5k次,点赞7次,收藏59次。基本思想:最近想尝试一下nano 上部署nanodet,于是记录一下训练过程,手中有一份labelme标注的数据集,于是开始了一波操作~首先将图片和json数据集转成xml (https://blog.csdn.net/sxj731533730/article/details/90046780),然后将xml数据集转成voc;import sysimport osimport jsonimport xml.etree.ElementTree as ETfrom PIL import Im_nanodet
文章浏览阅读930次。code::blocks + wxWidgets 2.8 在ubuntu 10.04下的安装p { margin-bottom: 0.21cm; }1、首先安装必要组件代码:安装编译器 sudo apt-get install build-essential
文章浏览阅读4.4k次,点赞10次,收藏38次。最终效果 整个项目都是基于swing实现的。窗是口将图片加载到JPanel面板,然后将面板添加到到JFrame窗口实现显示。这个类是选择几只像素鸟的类,也是main函数里执行的方法,代码有详细的注释,这里就不废话了public class select extends JPanel { /** * */ private static final long serialVersio..._java swing小游戏
文章浏览阅读8.7k次。三分钟教你读懂支票是什么支票1、支票的概念及特点支票:出票人签发的,委托办理支票存款业务的银行或其他金融机构在见票时无条件支付确定金额给收款人或持票人的票据。支票必填项:支票字样、确定的金额、出票日期、无条件支付委托、付款人名称、出票人签章。支票选填项:付款地、出票地。支票结算特点:(1)简便,手续_支票的原理是什么
文章浏览阅读148次。计算机教学实验中心成立于1999年,隶属计算机科学与技术学院。实验中心现有软件、电子、网络、通信、大学生科技创新、AR技术研究所等41间实验室,实验面积5600平方米,固定资产3500万元,教(职)工26人。实验中心以先进精良的设备条件、整洁舒适的教学环境、科学严谨的管理方式为计算机科学与技术学院、信息与电子工程学院、管理科学与工程学院等学院的实验教学、课程设计、毕业设计等实践环节和全院计算机公共..._计算机科学与技术实验教学中心 山东
文章浏览阅读10w+次,点赞45次,收藏82次。cuda errorRuntimeError: cuda runtime error (59) : device-side assert triggered at ...我之前还以为是因为GPU抽风了引发的BUG,所以第一次没有在意,直接又重新开始运行了一次,但是第二次就发现程序在同样的地方断掉了,这也就想起来我以前看到的一个博客,里面有句话的大概意思是这样的:每次都在同样的地方出错的..._cuda error: device-side assert triggered
文章浏览阅读1.1k次,点赞4次,收藏5次。在Vue中可非常便利地进行事件处理,例如:点击事件、鼠标悬停事件等。_vue html里面如何直接写事件函数
文章浏览阅读4.5k次,点赞15次,收藏67次。南京邮电大学离散数学实验一(求主析取和主合取范式)_离散数学实验
文章浏览阅读1.5w次,点赞2次,收藏5次。1.在springcloud中服务的 Instance ID 默认值是:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}},也就是:主机名:应用名:应用端口。如图12.可以自定义:eureka.instance...._spring.cloud.client.ip-address
文章浏览阅读2.1w次,点赞6次,收藏63次。OTB分为:OTB50和OTB100官方下载链接为:OTB官方数据集网站http://cvlab.hanyang.ac.kr/tracker_benchmark/datasets.html百度云链接:链接:https://pan.baidu.com/s/1Ck51d7OQ8w8BGcTL9UtopA提取码:jn0k复制这段内容后打开百度网盘手机App,操作更方便哦其中50和100,分别..._otb数据集官网
文章浏览阅读5.1k次。从Xcode菜单栏里打开Xcode -> Preferences -> Components -> Simulators,下载对应版本的模拟器。由于模拟器相关文件较大,下载时间较长,需要耐心等待,下载完成后,对应版本的模拟器前面的下载按钮就会变成下载完成的样式。点击Xcode菜单栏 Window -> Devices,然后可以看到设备列表,然而在模拟器列表(..._xcode模拟器切换ios版本
文章浏览阅读270次。CSV文件是一种以逗号或其他分隔符分隔的文件格式,用于存储表格数据。它可以用任何文本编辑器打开,并且非常适合在电子表格程序(例如Microsoft Excel或Google Sheets)中打开和处理。CSV文件通常由一组记录组成,每条记录包含一个或多个字段。字段之间使用逗号或其他指定的分隔符分隔。CSV文件中的第一行通常包含列标题,这些标题描述了每个字段的含义。Jack,19,UK本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。_python的csv拆列