Spring DI applicationContext.xml, как именно используется xsi: schemaLocation?

Примечание: тестовый проект, о котором я упоминаю, можно загрузить с помощью:

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

.. и запустите "ant run".

Я понимаю, что имена пространства имен XML просто используются как непрозрачные идентификаторы и не предназначены для использования в качестве URI (wikipedia). Я также понимаю, что расположение схем XML предназначено для предоставления подсказок относительно фактического расположения документов схемы и, будучи намеками, не используется на практике (w3.org). Имея это в виду, я экспериментировал с простым приложением Spring DI (используется в простой настройке J2SE), изменяя applicationContext.xml. Вот стартовая версия:                                                                                

<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. Однако, когда я исказил schemaLocations, добавив простое подчеркивание ко второму URL-адресу в каждой паре, я получил следующую жалобу:

 [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 использует второй URL в каждой паре в xsi: schemaLocation как некоторый идентификатор (жестко закодированный в его логике, поскольку нет доступа к сети). Поэтому мое предположение состояло бы в том, что среда выполнения Spring DI использует два типа идентификаторов для каждого пространства имен: идентификатор xmlns для уникальной идентификации пространства имен (используется как непрозрачная строка) и schemaLocation, чтобы однозначно идентифицировать версию схемы для этого пространства имен (снова используется как непрозрачная строка). То есть schemaLocation фактически используется (в искаженном виде, поскольку это не похоже на намерение документов w3c) на версию пространства имен. Более того, в таком случае, почему не работает среда выполнения Spring DI, о нехватке schemaLocation для пространства имен p. Является ли моя ментальная модель правильной?

Ответ 1

Вот что происходит:

  • XML-схема позволяет вам определять псевдонимы (короткие имена) в пространствах имен XML. Технически все пространства имен идентифицируются с помощью полного URI, но это было бы очень громоздким, поэтому вы можете использовать короткие псевдонимы типа context и p. Существует также пространство имен по умолчанию, обозначаемое атрибутом xmlns

  • По умолчанию XML-парсеры предполагают, что URI пространства имен также является расположением URL-адреса файла XSD. Это часто бывает, но спецификацией не требуется. Так же работает XML-парсер в Spring, если вы не предоставляете атрибут schemaLocation.

  • schemaLocation используется для сопоставления из URI пространства имен в физическое местоположение файла XSD (URL). Он используется, когда пространство имен схемы не указывает на действительный URL XSD (см. MSDN на schemaLocation).

  • Наконец, Spring добавляет еще один слой, который переводит интернет-адреса в локальные файлы на CLASSPATH. Таким образом ваше приложение может запускаться без подключения к Интернету (или когда сайт 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