Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
353 views
in Technique[技术] by (71.8m points)

dependency injection - Spring DI applicationContext.xml how exactly is xsi:schemaLocation used?

Note: the test project I'm mentioning can be downloaded with:

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

.. and run with 'ant run'.

I 'understand' that XML namespace names are just used as opaque identifiers and not meant to be used as URIs (wikipedia). I also 'understand' that the XML schema locations are meant to provide hints as to the actual location of schema documents and, being hints, not used in practice (w3.org). With that in mind I 've been experimenting with a simple Spring DI application (used in a simple J2SE setting) by modifying the applicationContext.xml. Here is the starting version:

<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}"/>                          

When I did a 'sudo ifconfig eth0 down' the project ran perfectly which is consistent with the runtime not bothering to fetch anything from the schemaLocations. However, when I mangled the schemaLocations by adding a simple underscore to the second URL in each pair I received the following complaint:

 [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)

Which seems to suggest that Spring DI runtime uses the second URL in each pair at the xsi:schemaLocation as some kind of identifier (hardcoded in its logic since there is no network access). So my assumption would be that the Spring DI runtime uses two kind of identifiers for each namespace: the xmlns identifier to uniquely identify the namespace (used as an opaque string) and the schemaLocation identifier to uniquely identify the schema version for that namespace (again used as an opaque string). I.e. the schemaLocation is actually used (in a contorted way ? as that doesn't seem to be the intention of the w3c documents) to version the namespace. Moreover, in such a case, why doesn't the Spring DI runtime complain about the lack of a schemaLocation for the "p" namespace. Is my mental model correct?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is what happens:

  • XML schema allows you to define aliases (short names) to XML namespaces. Technically all namespaces are identified by full URI but that would be very cumbersome - so you can use short aliases like context and p. There is also a default namespace denoted by xmlns attribute

  • By default XML parsers assume namespace URI is also a XSD file URL location. This is often the case, but is not required by the spec. This is also how XML parser in Spring works if you don't provide schemaLocation attribute.

  • schemaLocation is used to map from namespace URI to XSD file physical location (URL). It is used when schema namespace does not point to valid XSD URL (see MSDN on schemaLocation).

  • Last but not least, Spring adds yet another layer that translates Internet URLs to local files on CLASSPATH. This way your application can start without Internet connection (or when springframework.org site is down).

If you search your project libraries you'll find several files named spring.schemas. These files contain lines similar to below (extract from the file found in spring-context.jar, I added alignment):

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...