Spring DI applicationContext.xml xsi:schemaLocation 究竟是如何使用的?

Posted

技术标签:

【中文标题】Spring DI applicationContext.xml xsi:schemaLocation 究竟是如何使用的?【英文标题】:Spring DI applicationContext.xml how exactly is xsi:schemaLocation used? 【发布时间】:2012-06-01 21:21:00 【问题描述】:

注意:我提到的测试项目可以通过以下方式下载:

git 克隆https://github.com/mperdikeas/so-spring-di-appcontext-schemalocation.git

.. 并使用 'ant run' 运行。

我“理解”XML 命名空间名称只是用作不透明的标识符,而不是用作 URI (wikipedia)。我还“理解”XML 模式位置旨在提供有关模式文档实际位置的提示,并且作为提示,在实践中未使用 (w3.org)。考虑到这一点,我一直在通过修改 applicationContext.xml 来试验一个简单的 Spring DI 应用程序(用于简单的 J2SE 设置)。这是起始版本:

<beans xmlns             = "http://www.springframework.org/schema/beans"                                             
      xmlns:xsi         = "http://www.w3.org/2001/XMLSchema-instance"                                               
      xmlns:context     = "http://www.springframework.org/schema/context"                                           
      xmlns:p           = "http://www.springframework.org/schema/p"                                                 
      xsi:schemaLocation="http://www.springframework.org/schema/beans                                               
                          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd                          
                          http://www.springframework.org/schema/context                                             
                         http://www.springframework.org/schema/context/spring-context-2.5.xsd">                    

<context:component-scan base-package="atm"/>                                                                       
<context:property-placeholder location="classpath:META-INF/spring/atm.properties"/>                                

<bean id="soapTransport_" class="atm.SoapATMTransport" p:retries="$transport.retries"/>                          

当我执行“sudo ifconfig eth0 down”时,项目运行完美,这与运行时一致,无需费心从 schemaLocations 中获取任何内容。但是,当我通过在每对中的第二个 URL 中添加一个简单的下划线来破坏 schemaLocations 时,我收到了以下投诉:

 [java] org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 10 in XML document from class path resource [META-INF/spring/applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 10; columnNumber: 100; cvc-elt.1: Cannot find the declaration of element 'beans'.
 [java]     at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:194)
 [java]     at org.apache.tools.ant.taskdefs.Java.run(Java.java:771)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:221)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:135)
 [java]     at org.apache.tools.ant.taskdefs.Java.execute(Java.java:108)
 [java]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 [java]     at org.apache.tools.ant.Task.perform(Task.java:348)
 [java]     at org.apache.tools.ant.Target.execute(Target.java:390)
 [java]     at org.apache.tools.ant.Target.performTasks(Target.java:411)
 [java]     at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
 [java]     at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
 [java]     at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
 [java]     at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
 [java]     at org.apache.tools.ant.Main.runBuild(Main.java:809)
 [java]     at org.apache.tools.ant.Main.startAnt(Main.java:217)
 [java]     at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
 [java]     at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

这似乎表明 Spring DI 运行时使用 xsi:schemaLocation 处每对中的第二个 URL 作为某种标识符(在其逻辑中硬编码,因为没有网络访问)。所以我的假设是 Spring DI 运行时为每个命名空间使用两种标识符:xmlns 标识符来唯一标识命名空间(用作不透明字符串)和 schemaLocation 唯一标识该命名空间的架构版本的标识符(再次用作不透明字符串)。 IE。 schemaLocation 实际上被使用(以一种扭曲的方式?因为这似乎不是 w3c 文档的意图)来对命名空间进行版本控制。 此外,在这种情况下,为什么 Spring DI 运行时不抱怨“p”命名空间缺少 schemaLocation。我的心智模型正确吗?

【问题讨论】:

【参考方案1】:

会发生什么:

XML 模式允许您为 XML 命名空间定义别名(简称)。从技术上讲,所有命名空间都由完整的 URI 标识,但这会非常麻烦 - 因此您可以使用像 contextp 这样的短别名。还有一个由xmlns 属性表示的默认命名空间

默认情况下,XML 解析器假定命名空间 URI 也是 XSD 文件 URL 位置。这通常是这种情况,但不是规范要求的。如果您不提供 schemaLocation 属性,这也是 Spring 中 XML 解析器的工作方式。

schemaLocation 用于从命名空间 URI 映射到 XSD 文件物理位置 (URL)。当架构命名空间指向有效的 XSD URL(请参阅MSDN on schemaLocation)时使用它。

最后但同样重要的是,Spring 添加了另一个层,将 Internet URL 转换为 CLASSPATH 上的本地文件。这样,您的应用程序可以在没有 Internet 连接的情况下启动(或者当 springframework.org 站点关闭时)。

如果您搜索项目库,您会发现几个名为 spring.schemas 的文件。这些文件包含类似于下面的行(从spring-context.jar 中找到的文件中提取,我添加了对齐方式):

http\://www.springframework.org/schema/context/spring-context.xsd= org/springframework/context/config/spring-context-3.1.xsd
http\://www.springframework.org/schema/jee/spring-jee.xsd=         org/springframework/ejb/config/spring-jee-3.1.xsd
http\://www.springframework.org/schema/lang/spring-lang.xsd=       org/springframework/scripting/config/spring-lang-3.1.xsd
http\://www.springframework.org/schema/cache/spring-cache.xsd=     org/springframework/cache/config/spring-cache-3.1.xsd

【讨论】:

谢谢,这是一个清晰的模型。如果可以的话,还有两个问题:[1] 在我的项目库中只有一个 spring.schemas 文件(在 spring.jar 中),它似乎不包含诸如您为“xsi”描述的映射和'p' 命名空间(虽然我可以找到 'context' 和根命名空间映射),[2] 映射的东西记录在哪里? @MenelaosPerdikeas:不幸的是,我不知道 [1] 和 [2] 的答案。

以上是关于Spring DI applicationContext.xml xsi:schemaLocation 究竟是如何使用的?的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码从开始到放弃

jap_spring

Spring基础:XML方式实现DI

ssm applicationContent.xml

Spring万字详解DI相关内容,一文掌握DI配置与使用

Spring依赖注入 DI