服装网站建设与规划南沙网站建设wwiw

张小明 2026/1/14 1:26:33
服装网站建设与规划,南沙网站建设wwiw,wordpress弹窗,wordpress 发送请求XML命名空间到标签解析 回顾上一章节 在上一篇文章中#xff0c;我们深入探索了 Spring 如何加载 XML 配置并解析为 BeanDefinition 的骨架结构#xff1a; Spring 通过 doRegisterBeanDefinitions 方法实现了解析的核心流程通过保存和恢复 delegate 实现了嵌套 beans…XML命名空间到标签解析回顾上一章节在上一篇文章中我们深入探索了 Spring 如何加载 XML 配置并解析为 BeanDefinition 的骨架结构Spring 通过doRegisterBeanDefinitions方法实现了解析的核心流程通过保存和恢复delegate实现了嵌套beans标签之间的属性隔离通过三步走策略预处理→解析→后处理提供了灵活的扩展点通过深度遍历的方式处理 XML 节点区分默认命名空间和自定义命名空间关键理解在解析过程中Spring 需要区分不同的命名空间并找到对应的解析器来处理标签。那么Spring 是如何从命名空间找到对应的解析器的呢统一术语在开始之前我们先明确几个关键术语命名空间NamespaceXML 中的命名空间用于区分不同来源的标签如http://www.springframework.org/schema/beansNamespaceHandler命名空间处理器负责处理特定命名空间下的所有标签BeanDefinitionParserBean 定义解析器负责将 XML 元素解析为BeanDefinitionNamespaceHandlerResolver命名空间处理器解析器负责根据命名空间找到对应的NamespaceHandler自定义命名空间除了 Spring 默认命名空间外的其他命名空间如http://www.springframework.org/schema/context问题场景当我们使用 Spring 时XML 配置文件中可能包含多种命名空间的标签?xml version1.0 encodingUTF-8?beansxmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocation...!-- 默认命名空间的bean标签 --beaniduserServiceclasscom.example.UserService/!-- context命名空间的标签 --context:component-scanbase-packagecom.example/!-- aop命名空间的标签 --aop:configaop:aspectrefloggingAspect//aop:config/beans核心问题Spring 如何识别不同的命名空间当遇到context:component-scan时Spring 如何知道这是context命名空间的标签如何找到对应的解析器不同的命名空间需要不同的解析器Spring 是如何建立命名空间和解析器之间的映射关系的自定义命名空间如何工作如果我们想定义自己的命名空间需要实现哪些接口解析器是如何被调用的从命名空间到最终调用解析器的完整流程是怎样的这些问题看似复杂但深入思考会发现它们背后有一套清晰的机制。让我们从源码中寻找答案。源码探索第一步理解命名空间的设置机制我们之前读取 XML 的章节实际上是一带而过的因为它主要使用了三方件将 XML 文件读取为 Document 对象。这之中有个很重要的概念没有澄清解析得到的 Document 对象对于每一个标签都会设置其命名空间。例如beans标签的命名空间是http://www.springframework.org/schema/beansaop:config标签的命名空间则是http://www.springframework.org/schema/aop理解这些命名空间如何被设置的呢按照xmlns指定的路径网络 or 本地文件匹配标签进而设置标签所属的命名空间。⚠️需要澄清关于命名空间的设置机制有一个细节需要确认命名空间的声明方式命名空间是通过xmlns属性声明的但声明和设置是两个不同的概念。XML 解析器在解析时会根据xmlns声明和标签的前缀来确定每个标签的命名空间。命名空间 URI 的作用命名空间 URI如http://www.springframework.org/schema/beans是一个标识符它不一定需要实际访问网络或本地文件。它只是用来唯一标识一个命名空间。XSD 文件的作用XSD 文件主要用于验证XML 的结构是否符合规范而不是用来设置命名空间。命名空间在 XML 解析时就已经确定了。建议可以查看一下 XML 解析器如 DOM 解析器是如何处理xmlns声明的以及Element.getNamespaceURI()方法是如何获取命名空间的。这样能更准确地理解命名空间的设置机制。当然我们如果目标是学习 Spring 源码这里可以忽略。第二步parseCustomElement 方法的核心逻辑为什么要特意讲命名空间呢是因为我们接下来看的parseCustomElement方法和命名空间关系密切。在上一章节中我们也讲过这个方法适用于解析非 Spring Bean 命名空间标签的。让我们看看BeanDefinitionParserDelegate中的parseCustomElement方法publicBeanDefinitionparseCustomElement(Elementele){returnparseCustomElement(ele,null);}publicBeanDefinitionparseCustomElement(Elementele,BeanDefinitioncontainingBd){// 1. 获取标签的命名空间StringnamespaceUrigetNamespaceURI(ele);// 2. 通过上下文中的 NamespaceHandlerResolver 获取命名空间处理器NamespaceHandlerhandlerthis.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);if(handlernull){error(Unable to locate Spring NamespaceHandler for XML schema namespace [namespaceUri],ele);returnnull;}// 3. 使用处理器解析该标签returnhandler.parse(ele,newParserContext(this.readerContext,this,containingBd));}发现一方法的核心逻辑分为三步获取标签的命名空间通过getNamespaceURI(ele)从 Element 对象中获取该标签所属的命名空间 URI通过上下文中的 NamespaceHandlerResolver 获取命名空间处理器根据命名空间 URI找到对应的NamespaceHandler使用处理器解析该标签调用NamespaceHandler的parse方法将 XML 元素解析为BeanDefinition关键理解命名空间是连接 XML 标签和解析器的桥梁。Spring 通过命名空间来区分不同的标签并为每个命名空间找到对应的处理器。类比理解这就像快递分拣每个包裹XML 标签上都有一个地址命名空间分拣员NamespaceHandlerResolver根据地址找到对应的分拣中心NamespaceHandler然后由分拣中心处理这个包裹。第三步DefaultNamespaceHandlerResolver 如何解析并返回命名空间处理器获取命名空间刚刚已经讲过接下来就看DefaultNamespaceHandlerResolver如何解析并返回命名空间处理器了。让我们看看DefaultNamespaceHandlerResolver的resolve方法publicNamespaceHandlerresolve(StringnamespaceUri){// 1. 获取处理器映射关系懒加载MapString,ObjecthandlerMappingsgetHandlerMappings();// 2. 从映射中获取处理器类名ObjecthandlerOrClassNamehandlerMappings.get(namespaceUri);if(handlerOrClassNamenull){returnnull;}// 3. 如果已经是实例直接返回if(handlerOrClassNameinstanceofNamespaceHandler){return(NamespaceHandler)handlerOrClassName;}// 4. 如果是类名则解析处理器实例化、初始化、缓存StringclassName(String)handlerOrClassName;returnresolve(className);}可以看到这个类中有两个重要的方法1. 获取处理器映射关系getHandlerMappings这是一个懒加载机制首次使用时加载依靠双检查double-check实现仅加载一次。privateMapString,ObjectgetHandlerMappings(){MapString,ObjecthandlerMappingsthis.handlerMappings;if(handlerMappingsnull){synchronized(this){handlerMappingsthis.handlerMappings;if(handlerMappingsnull){handlerMappingsnewHashMap();// 加载所有 META-INF/spring.handlers 文件loadAllProperties(this.handlerMappingsLocation,handlerMappings);this.handlerMappingshandlerMappings;}}}returnhandlerMappings;}发现二通过spring-core包中提供的loadAllProperties方法可以得到 classpath 下所有META-INF/spring.handlers目录文件的 properties 配置。理解通过这里得到的实际上是命名空间 URI-命名空间解析器全限定类名的关系。例如META-INF/spring.handlers文件可能包含http://www.springframework.org/schema/contextorg.springframework.context.config.ContextNamespaceHandler http://www.springframework.org/schema/aoporg.springframework.aop.config.AopNamespaceHandler http://www.springframework.org/schema/txorg.springframework.transaction.config.TxNamespaceHandler发现三Spring 通过约定优于配置的方式让各个模块在自己的 jar 包中提供META-INF/spring.handlers文件Spring 会自动扫描并加载这些映射关系。2. 解析处理器resolve 方法的重载版本主要是根据获得的命名空间 URI-命名空间解析器全限定类名的关系根据命名空间 URI 找到命名空间解析器类然后privateNamespaceHandlerresolve(StringclassName){try{// 1. 实例化通过反射创建 NamespaceHandler 实例Class?handlerClassClassUtils.forName(className,this.classLoader);NamespaceHandlerhandler(NamespaceHandler)BeanUtils.instantiateClass(handlerClass);// 2. 初始化调用 init() 方法进行初始化handler.init();// 3. 缓存放入 handlerMappings 中下次使用则不需要再次实例化和初始化了this.handlerMappings.put(namespaceUri,handler);returnhandler;}catch(ClassNotFoundExceptionex){thrownewFatalBeanException(NamespaceHandler class [className] not found,ex);}}发现四实例化通过反射创建NamespaceHandler实例初始化调用init()方法进行初始化注册该命名空间下的各种标签解析器缓存放入原有的MapString, Object handlerMappings中下次使用则不需要再次实例化和初始化了关键理解这样几步操作就返回了命名空间专属解析器。通过懒加载和缓存机制既保证了性能又实现了按需加载。类比理解这就像图书馆的借书系统第一次借书时需要先查目录加载映射关系然后找到对应的书架实例化处理器把书的位置记录下来缓存下次再借同样的书时直接去记录的位置拿就行了。第四步其他解析器的解析过程暂不展开根据其他解析器解析的过程就暂时不展开学习等到学习 AOP、事务TX、JDBC 时再做深入了解也不迟。学习策略现在我们已经理解了从命名空间到解析器的完整机制这已经足够理解 Spring 的命名空间解析框架了。具体的解析器实现如ContextNamespaceHandler、AopNamespaceHandler等会在后续学习相应功能模块时再深入探索。设计思想1. 策略模式的应用Spring 通过NamespaceHandler接口定义了命名空间处理的策略不同的命名空间有不同的实现类如ContextNamespaceHandler、AopNamespaceHandler等。这种设计让 Spring 可以灵活地支持多种命名空间并且易于扩展。类比理解就像不同的快递公司有不同的处理流程但都遵循统一的接口规范Spring 可以根据不同的命名空间选择不同的处理策略。2. 约定优于配置Spring 通过约定META-INF/spring.handlers文件的位置和格式让各个模块可以自动注册自己的命名空间处理器。开发者不需要手动配置只需要按照约定提供配置文件即可。发现这种设计让 Spring 的扩展机制变得非常灵活任何模块都可以通过提供META-INF/spring.handlers文件来注册自己的命名空间处理器。3. 懒加载和缓存机制DefaultNamespaceHandlerResolver使用了懒加载和缓存机制懒加载只有在需要时才加载映射关系和实例化处理器避免不必要的初始化开销双检查锁定确保在多线程环境下映射关系只加载一次缓存实例化后的处理器会被缓存避免重复创建性能优化这种设计既保证了性能按需加载又保证了线程安全双检查锁定还避免了重复创建缓存。4. 职责分离NamespaceHandlerResolver负责根据命名空间 URI 找到对应的处理器NamespaceHandler负责处理特定命名空间下的标签解析BeanDefinitionParser负责将具体的 XML 元素解析为BeanDefinition发现这种职责分离的设计让代码结构更清晰每个类都有明确的职责便于维护和扩展。5. 可扩展性设计Spring 的命名空间机制是完全可扩展的开发者可以定义自己的命名空间实现NamespaceHandler接口提供META-INF/spring.handlers文件实现具体的BeanDefinitionParser这样就能让 Spring 支持自定义的 XML 标签实现自己的配置方式。大白话总结让我们用大白话再梳理一遍1. 这篇文章讲的是什么简单说Spring 如何根据 XML 标签的命名空间找到对应的解析器来处理这个标签。类比就像快递分拣每个包裹XML 标签上都有一个地址命名空间分拣员NamespaceHandlerResolver根据地址找到对应的分拣中心NamespaceHandler然后由分拣中心处理这个包裹。2. 命名空间是如何设置的简单说XML 解析器在解析 XML 文件时会根据xmlns声明和标签的前缀自动为每个标签设置命名空间。命名空间 URI 是一个标识符用来唯一标识一个命名空间。类比就像身份证号码每个命名空间都有一个唯一的 URI用来区分不同的命名空间。3. Spring 如何找到对应的解析器简单说加载映射关系Spring 会扫描 classpath 下所有的META-INF/spring.handlers文件得到命名空间 URI-处理器类名的映射关系实例化处理器根据命名空间 URI 找到对应的处理器类通过反射创建实例初始化处理器调用init()方法注册该命名空间下的各种标签解析器缓存处理器将实例化后的处理器缓存起来下次直接使用类比就像图书馆的借书系统第一次借书时需要查目录加载映射关系找到书架实例化处理器记录位置缓存下次直接去拿就行了。4. 为什么要用懒加载和缓存简单说懒加载只有在需要时才加载避免不必要的初始化开销缓存避免重复创建提高性能类比就像点外卖你不需要提前把所有餐厅的菜单都下载下来懒加载点过的餐厅菜单会被记住缓存下次点同样的餐厅时直接显示就行了。5. 如何扩展自己的命名空间简单说定义自己的命名空间 URI实现NamespaceHandler接口提供META-INF/spring.handlers文件配置映射关系实现具体的BeanDefinitionParser来解析标签类比就像开一家新的快递公司你需要注册公司定义命名空间建立分拣中心实现 NamespaceHandler在系统中登记提供配置文件然后就可以处理包裹解析标签了。总结通过这篇文章我们深入探索了 Spring 如何从命名空间找到对应的解析器的完整机制核心流程命名空间的设置XML 解析器根据xmlns声明自动为每个标签设置命名空间获取命名空间通过Element.getNamespaceURI()获取标签的命名空间 URI加载映射关系从META-INF/spring.handlers文件加载命名空间 URI-处理器类名的映射关系解析处理器根据命名空间 URI 找到对应的处理器类实例化、初始化并缓存解析标签调用处理器的parse方法将 XML 元素解析为BeanDefinition关键设计策略模式通过NamespaceHandler接口定义处理策略不同命名空间有不同的实现约定优于配置通过约定META-INF/spring.handlers文件的位置和格式实现自动注册懒加载和缓存按需加载避免不必要的初始化开销提高性能职责分离每个类都有明确的职责便于维护和扩展可扩展性完全可扩展开发者可以定义自己的命名空间和解析器思考题为什么 Spring 要使用命名空间来区分不同的标签如果不使用命名空间会有什么问题懒加载和缓存机制是如何保证线程安全的双检查锁定的原理是什么如何实现一个自定义的命名空间需要实现哪些接口提供哪些配置文件NamespaceHandler的init()方法做了什么为什么需要在初始化时注册标签解析器延伸阅读Spring 源码NamespaceHandlerSpring 源码NamespaceHandlerResolverSpring 源码DefaultNamespaceHandlerResolverSpring 源码BeanDefinitionParserDelegate上一篇文章XML配置加载BeanDefinition的骨架
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

网站开发考什么证定制旅游网站有哪些

MLX90640红外热像仪终极指南:从零到精通完整流程 【免费下载链接】mlx90640-library MLX90640 library functions 项目地址: https://gitcode.com/gh_mirrors/ml/mlx90640-library 想要快速上手MLX90640红外热像仪驱动开发吗?这篇终极指南将带你从…

张小明 2026/1/5 15:50:49 网站建设

网站统计数据怎么做c成apa格式sae 网站模板

Keil调试实战:手把手教你用单步执行“拆解”STM32程序你有没有遇到过这种情况——代码烧进去,板子上电,LED不亮、串口没输出,程序就像进了黑洞,完全不知道卡在哪?打印调试加一堆printf,结果发现…

张小明 2026/1/9 18:27:33 网站建设

网站开发结构文档白云网站 建设信科网络

数据备份、恢复与网络安全指南 在当今数字化时代,数据备份与恢复以及网络安全是企业运营中至关重要的环节。有效的数据备份策略能确保在系统故障或数据丢失时迅速恢复业务,而完善的网络安全措施则可保护企业信息免受非法访问和攻击。本文将详细介绍相关的技术细节和关键路径…

张小明 2026/1/10 6:42:17 网站建设

网站设计编程好看的图案设计

第一章:为什么顶级团队都在用Dify集成Spring AI?揭秘背后的架构优势在AI应用快速迭代的今天,顶级开发团队正转向Dify与Spring AI的深度集成方案,以实现敏捷开发与企业级能力的双重目标。这一组合不仅提升了AI服务的可维护性&#…

张小明 2026/1/1 16:40:25 网站建设

怎么做一个网站出来星光影视园网站建设案例

VMware解锁器终极指南:在Windows/Linux上运行macOS虚拟机 【免费下载链接】unlocker 项目地址: https://gitcode.com/gh_mirrors/unlo/unlocker 项目概述与核心价值 VMware macOS Unlocker是一款革命性的系统兼容工具,专为希望在非苹果硬件上体…

张小明 2026/1/9 15:48:45 网站建设

公司介绍网站怎么做广西建设工程协会网站

5步掌握Vue-D3-Network:构建专业级网络图谱可视化应用 【免费下载链接】vue-d3-network Vue component to graph networks using d3-force 项目地址: https://gitcode.com/gh_mirrors/vu/vue-d3-network 还在为如何在Vue项目中实现复杂的网络关系图而烦恼吗&…

张小明 2026/1/2 0:30:43 网站建设