之所以讲解DefaultNamespaceHandlerResolver类,是因为这个类跟解析xml的时候有着莫大的关联。并且从中也可以学到一些构建代码方法,先看一下我们的配置文件,一般我们会以这样的开头
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 。。。。。。。
其中的http://www.springframework.org/schema/beans,http://www.springframework.org/schema/aop,http://www.springframework.org/schema/context等这些是xml的命名空间。而spring解析xml的时候就是采用的方法和管理方法有点类似,就是分而治之,给你画一块地,这个就归你管理了,该怎么办就怎么办。spring解析xml的时候就是不同的xml名称空间用不同的类来解析,这样也是解耦了代码,同时更加容易扩展。下面就慢慢的揭开spring解析xml的面纱。。。。。。
如果 还没看前面一篇解析xml的文章,建议先看一下!spring解析xml到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; //解析Beans标签等 if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { //解析其他的命名空间 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
如果是其他的命名空间会到BeanDefinitionParserDelegate,这个类就是负责根据不同的xml名称空间分发解析xml了,就像公司的Boss,他负责给每个部门的老大任务。根据什么样的方式来分配任务呢?且看下面:
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); //这里的getNamespaceHandlerResolver就像是秘书,根据不同的任务找到不同部门 //这里的readerContext就是Boss了 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } //这里的readerContext就是解析上下文,用于不同类解析完成后像容器注册BeanDefinition return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
公司的Boss想了一下,你们每个部门不的都有名称么,每个部门自己的职能Boss自己不知道就找秘书,根据这些来分配任务了。spring也是一样,你xml标签不是都有自己的名称空间么,好我就以名称空间给你一亩地。你就负责好管理你这块地了。但是Boss怎么知道下面的每个部门完成任务了呢?是不是要实时的监控下,给每个部门老大办公室安装一个视频监控器。Boss就每天坐家里看你们有没有完成。要是这样那估计部门老大干完一天就走人了,大爷我不干了。你这监视我,就是不信任我啊,再说我还哪有自由可言,还没隐私了。不干了。呵呵,Boss想了一下不能这么干。high不了啊。好,那我就给你一个接口,你干好了,你就自动提交任务吧。这里的readerContext就是这样的接口了。这次我也完全信用你了,都不给你时间限制。你就慢慢玩吧。这样的Boss,估计每个部门老大都很high了。
但是Boss在什么地方去根据什么样的任务分配给部门呢?Boss肯定都有一个秘书,找秘书吧。(怎么创建Boss和秘书的就要看解析xml了)嗯,秘书就乖乖给Boss一个本子,记录着呢,都在DefaultNamespaceHandlerResolver这个记事薄上,在下面的一页:
public NamespaceHandler resolve(String namespaceUri) { //秘书从资料夹上得到资料 Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } //创建一个部门 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //这个是部门创建后招员工的方法,会在下面讲解 namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } } /** * Load the specified NamespaceHandler mappings lazily. */ private Map<String, Object> getHandlerMappings() { //不幸,秘书第一次找到是空的,那就初始化吧 if (this.handlerMappings == null) { synchronized (this) { if (this.handlerMappings == null) { try { //秘书通过工具PropertiesLoaderUtils查找资料吧,不能手工啊,多麻烦 //这里的资料都记在叫META-INF/spring.handlers这个名字的架上,并且这样的架还挺多的 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded NamespaceHandler mappings: " + mappings); } Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size()); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return this.handlerMappings; }
秘书就从资料架上找啊找,发现都记录在META-INF/spring.handlers这个名字的架上,然后通过PropertiesLoaderUtils工具全部找出来,记录在资料本某一页上。其中工具就是这样执行的。
public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException { Assert.notNull(resourceName, "Resource name must not be null"); ClassLoader clToUse = classLoader; if (clToUse == null) { clToUse = ClassUtils.getDefaultClassLoader(); } Properties props = new Properties(); Enumeration urls = clToUse.getResources(resourceName); while (urls.hasMoreElements()) { URL url = (URL) urls.nextElement(); URLConnection con = url.openConnection(); ResourceUtils.useCachesIfNecessary(con); InputStream is = con.getInputStream(); try { if (resourceName != null && resourceName.endsWith(XML_FILE_EXTENSION)) { props.loadFromXML(is); } else { props.load(is); } } finally { is.close(); } } return props; }
把所有classpath路径下META-INF/spring.handlers都找到并返回。这样秘书就可以回馈给Boss了。也可以交任务了。所以你到spring下的lib下看,会发现bean,aop,context,tx,jdbc等都会有 META-INF/spring.handlers文件。Boss根据秘书把任务分配好了,这里就要看部门老大怎么完成任务呢。这里讲一个实例,看其中的一个aop名称空间的解析,先看其jar文件下的META-INF/spring.handlers文件内容。发现啊aop的部门老大呢为AopNamespaceHandler类。
相关推荐
现在,我们将深入探讨Spring 4.0源码中的关键知识点。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一就是DI,它通过容器管理对象及其依赖关系,使代码更加灵活和可测试。在源码中,我们可以...
Spring 框架是 Java 开发中最广泛应用的轻量级框架之一,它的4.0.x版本在2013年发布,带来了许多重要的改进和新特性。本文将深入解析 Spring 4.0.x 的核心概念、主要改进以及关键组件。 一、Spring 概述 Spring 是...
通过学习Spring 4.0.x的源码,开发者不仅可以深入了解Spring的工作原理,还能学习到最佳实践和设计模式,这对于提升个人技能和解决实际问题大有裨益。深入研究每个模块的实现细节,有助于更好地利用Spring框架提供的...
《Spring 4.0框架深度探索:基于Maven构建的实战Demo》 Spring框架作为Java企业级应用开发的基石,自推出以来就以其强大的功能和灵活性赢得了广大开发者的心。Spring 4.0作为其一个重要版本,引入了许多改进和新...
Spring4.0版本是该框架的一个重要里程碑,它引入了多项增强功能和优化,提升了性能和开发者体验。在此,我们将深入探讨Spring4.0中的关键知识点。 首先,Spring4.0对Java版本的支持升级至Java 7,这意味着开发者...
8. **API清理**:Spring 4.0.x删除了许多已废弃的方法和类,以保持API的清洁和一致性。这种做法鼓励开发者使用最新的API,避免了依赖过时的代码。 9. **更好的类型安全**:Spring 4增强了类型安全,例如在Bean的...
这个"spring4.0完整jar包"包含了Spring4.0框架的所有核心组件和相关模块,使得开发者能够一站式获取所有必要的库,方便集成到项目中。 首先,让我们深入了解一下Spring框架的核心组成部分: 1. **IoC(Inversion ...
4. **改进的JDBC抽象层**:Spring 4.0的JdbcTemplate和NamedParameterJdbcTemplate类进行了优化,提高了性能并降低了内存占用。同时,增加了对JDBC 4.1和4.2规范的支持,包括更好的类型处理和批处理操作。 5. **...
Spring框架是Java开发中最广泛应用的轻量级...通过分析源码,我们可以学习到设计模式的运用,以及如何在大型项目中实现模块化和松耦合。此外,对源码的理解也有助于我们定制和扩展Spring框架,以满足特定的项目需求。
源码分析是提升技能的绝佳途径,Spring4.0的源码揭示了框架内部的工作机制。例如,你可以看到AOP(面向切面编程)如何实现、IoC(控制反转)容器如何管理Bean、以及事件监听和事务管理的底层逻辑。通过阅读源码,...
Spring 4.0版本是该框架的一个重要里程碑,引入了许多改进和新特性,使得开发者能够更加高效地工作。这篇指南将深入探讨Spring 4.0的关键知识点。 一、Spring核心模块 Spring的核心模块包括IoC(Inversion of ...
1. **spring-beans.jar**:这是Spring的核心组件之一,包含了Bean工厂和Bean定义,用于创建、配置和管理Java对象。它实现了IoC(Inversion of Control)容器,使得应用程序的组件可以被外部容器控制,而不是自行管理...
Spring4.0-API CHM格式,很难得的,希望能帮到大家!
spring4.0详细教程,简单明了,一看即懂 ,适合初学者
标题 "spring4.0+spring MVC4.0+hibernate4.3全注解" 涉及的是一个基于Java的Web开发技术栈,它整合了Spring 4.0、Spring MVC 4.0和Hibernate 4.3这三个流行框架。这个案例旨在展示如何在不使用XML配置的情况下,...
Spring4.0+Hibernate4.0+Struts2.3整合案例:实现增删改查。 ===================== application.xml: xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...
《Spring 4.0 Jar:核心框架的深度解析》 Spring 框架作为Java企业级应用开发的首选,其4.0版本的发布在业界引起了广泛关注。Spring 4.0 jar 包,包含了该版本所有开发所需的核心组件,使得开发者能够更便捷地构建...