Разница префикса пути к классам Spring


143

Документировано здесь говорится

Этот специальный префикс указывает, что все ресурсы пути к классам, которые соответствуют заданному имени, должны быть получены (внутренне это, по сути, происходит через вызов ClassLoader.getResources (...)), а затем объединены для формирования окончательного определения контекста приложения.

Кто-нибудь может это объяснить?

В чем разница между использованием classpath*:conf/appContext.xmlи classpath:conf/appContext.xmlбез звездочки.


Будущие читатели также увидят эту ошибку с пометкой «статус = отклонен». github.com/spring-projects/spring-framework/issues/16017 На всякий случай, если URL когда-либо в конечном итоге не сработает, заголовок сообщения об ошибке: «Импорт XML-файла из корня JAR-файла с подстановочным путем к классам и подстановочным путем не работает [SPR-11390] »
granadaCoder

Ответы:


209

ПРОСТОЕ ОПРЕДЕЛЕНИЕ

classpath*:conf/appContext.xmlПросто означает , что все файлы appContext.xml под confпапкой во всех ваших банках по классам будут собраны и объединены в один большой контекст приложения.

Напротив, classpath:conf/appContext.xmlзагрузится только один такой файл ... первый найденный в вашем пути к классам.


6
Между ними есть еще одно интересное отличие. См. Также мой вопрос: stackoverflow.com/questions/16985770/…
Евгений

29
Одна очень важная вещь - если вы используете * и Spring не находит совпадений, он не будет жаловаться. Если вы не используете * и совпадений нет, контекст не запустится (!)
Рой Трулав,

39

Этот classpath*:...синтаксис полезен в первую очередь, когда вы хотите создать контекст приложения из нескольких файлов определения bean-компонентов, используя синтаксис с подстановочными знаками.

Например, если вы создаете свой контекст с помощью classpath*:appContext.xml, путь к классам будет сканироваться для каждого ресурса, вызываемого appContext.xmlв пути к классам, и определения bean-компонентов из всех из них объединены в единый контекст.

Напротив, classpath:conf/appContext.xmlбудет получен один и только один файл, вызываемый appContext.xmlиз пути к классам. Если их несколько, остальные игнорируются.


2
Будет ли путь к классам * искать и в подкаталогах? Другими словами, если у меня есть appContext.xml в корне пути к классам и один в /dir/appContext.xml, загрузятся ли они оба, когда я использую путь к классам *: appContext.xml?
AHungerArtist

21

classpath *: он ссылается на список ресурсов и загружает все такие файлы, присутствующие в пути к классам, и список может быть пустым, и если такого файла нет в пути к классам, приложение не генерирует никаких исключений (просто игнорирует ошибку).

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

java.io.FileNotFoundException: class path resource [conf/appContext.xml] cannot be opened because it does not exist

Официальный документ «Невозможно использовать префикс classpath *: для создания фактического файла Resource, поскольку ресурс указывает только на один ресурс за раз». плюс я только что получил эту странную ошибку, вот как я оказался здесь. Если вы собираетесь импортировать ресурс, тогда нет смысла использовать префикс пути к классам с подстановочными знаками.
GabrielOshiro

0

Исходный код Spring:

public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   //CLASSPATH_ALL_URL_PREFIX="classpath*:"
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Only look for a pattern after a prefix here
      // (to not get fooled by a pattern symbol in a strange prefix).
      int prefixEnd = locationPattern.indexOf(":") + 1;
      if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
         // a file pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // a single resource with the given name
         return new Resource[] {getResourceLoader().getResource(locationPattern)};
      }
   }
}  

Не могли бы вы объяснить?
RTMY
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.