Предисловие
Для анализа принципа запуска самого Spring Boot, пожалуйста, см.
Отношения наследования ClassLoader в Spring Boot могут запускать демонстрацию, указанную ниже, и запустить его в разных сценариях. Вы можете знать отношения наследования ClassLoader в приложениях Spring Boot в разных сценариях.
https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-classloader-context
Есть три ситуации:
В IDE основная функция Run, непосредственно выполняющая класс -загрузчик Spring, напрямую SystemClassLoader. URL -адреса ClassLoader содержат все банки и их собственные цели/классы
===== =
URL -адреса ClassLoader: sun.misc.launcher$Appclassloader@2a139a55
Файл:/users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/classes/classes/
File: /Users/hengyunabc/.m2/repository/org/springframework/cloud/spring-cloud-starter/1.1.9.reelease/spring-cloud-starter-1.1..release.jar
File: /users/hengyunabc/.m2/repository/org/springframework/boot/spring-boot-starter/1.4.7.release/spring-boot-starter-1.4.7.release.jar
...
Бежать как толстая банка
MVN CLEAN PACKERJAVA -JAR TARGET/DEMO-ClassLoader-Context-0.0.1-snapshot.jar
ClassLoader, который выполняет основную функцию приложения, - это запущенная загрузчик, а его родителем является загрузчик SystemClass.
========= ClassLoader Tree ===============
org.springframework.boot.loader.launchedurlclassloader@1218025c
- sun.misc.launcher $appclassloader@6bc7c054
- sun.misc.launcher$extclassloader@85ede7b
И LaunchedURLClassLoader的urls -это BOOT-INF/classes!/ Directory в fat jar и все банки в Boot-Inf/Lib.
===== =
URL -адреса ClassLoader: org.springframework.boot.loader.launchedurlclassloader@1218025c
Jar: File: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar!/boot-inf/class!//
Jar: File: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar! /boot-inf/lib/spring-boot-1.4.7.release.jar!
Jar: File: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar! /boot-inf/lib/spring-web-5.9.release.jar!
...
URL-адреса SystemClassLoader являются demo-classloader-context-0.0.1-SNAPSHOT.jar .
========= Системный класс -загрузчик urls =============================
URL -адреса ClassLoader: sun.misc.launcher$Appclassloader@6bc7c054
File: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar
Работать как декомпрессированный каталог
MVN Clean Packagecd TargetUnzip Демо-класс-загрузчик-context-0.0.1-snapshot.jar -d demojava org.springframework.boot.loader.propertieslauncher
ClassLoader, который выполняет основную функцию приложения, - это LaunchedURLClassLoader , а его родителем является SystemClassLoader .
========= ClassLoader Tree ===============
org.springframework.boot.loader.launchedurlclassloader@4aa298b7
- sun.misc.launcher$appclassloader@2a139a55
- sun.misc.launcher$extclassloader@1b6d3586
URL-адреса LaunchedURLClassLoader -это пакеты JAR ниже BOOT-INF/classes/ и /BOOT-INF/lib/ в каталоге декомпрессии.
===== =
URL -адреса ClassLoader: org.springframework.boot.loader.launchedurlclassloader@4aa298b7
Файл:/users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/classes/class/class/
JAR: File: /Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/bcpkix-jdk15on-1.55.jar!///
JAR: File: /Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/bcprov-jdk15on-1.55.jar!////
Jar: File: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/classmate-1.3.3.jar!///
URL -адреса SystemClassLoader имеют только текущий каталог:
========= Системный класс -загрузчик urls =============================
URL -адреса ClassLoader: sun.misc.launcher$Appclassloader@2a139a55
Файл:/users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/
На самом деле, есть еще два способа запуска: mvn spring-boot:run и mvn spring-boot:run -Dfork=true , но он редко используется и не будет обсуждаться отдельно. Если вы чувствуете себя заинтересованным, вы можете сбежать самостоятельно.
Сводка взаимосвязи наследования класса загрузчика в Spring Boot
Когда основная функция выполняется в IDE, существует только один загрузчик класса, то есть SystemClassLoader
При запуске в качестве Fat Jar есть загрузка запуска
URL-адреса LaunchEdUrlClassloader-это банки под загрузкой-INF/Classes и Boot-Inf/LIB в Fat Jars. URL -адреса SystemClassloader сами являются жирными банками.
При запуске повторного разложения каталога он похож на Fat Jar, но URL находится в виде каталога. Формат каталогов будет иметь лучшую совместимость.
Версии пружины 1,3. и 1.4.
В Spring Boot 1.3.* Версия
Класс погрузчиков с пружинными загрузками помещается в жирную банку
Изменения структуры упаковки в Spring Boot 1.4 были введены этим коммитом
https://github.com/spring-projects/spring-boot/commit/87fe0b2adeef85c842c009bfeebac1c84af8a5d7
Первоначальное намерение этого коммита состоит в том, чтобы упростить отношения наследования класса-загрузчика, реализовать загрузчик запуска, первым интуитивно понятным родителем, и в то же время структура упаковки ближе к традиционному приложению пакета военного пакета.
Однако это изменение вызвало много сложных проблем. Из вышесказанного мы проанализировали наследство класса -загрузчика немного головокружение.
Некоторые воздействия текущих отношений наследования класса -загрузчика
Есть много пользователей, которые могут обнаружить, что какой -то код хорошо работает в IDE, но не работает, когда фактически развернут. Много раз это вызвано структурой загрузчика класса. Вот некоторые случаи.
demo.jar!/boot-inf/classes!/Таким образом, URL не работает
Потому что Spring Boot расширяет стандартный протокол JAR, позволяя ему поддерживать многослойную JAR в JAR и каталог в JAR. Обратитесь к анализу принципа запуска приложения Spring Boot
Несмотря на то, что в JAR в Spring Boot 1.3 будет JAR JAR, какой -то относительно надежный код может справиться с этой ситуацией, например, сама Tomcat8 поддерживает JAR в JAR.
Тем не менее, большая часть кода не будет поддерживать несколько URL-адресов, таких как demo.jar!/BOOT-INF/classes!/ , Так что в Spring Boot1.4 многие коды библиотеки будут недействительными.
Проблемы ресурсов в рамках Demo.jar!/Meta-Inf/Resources
В спецификации Сервлета 3.0 приложения могут размещать статические ресурсы в соответствии с мета-инф/ресурсами, а контейнер сервлета будет поддерживать чтение. Но из приведенных выше результатов наследования мы можем найти проблему:
Это создает некоторые странные явления:
Кроме того, официальный пример Spring Boot только поддерживает только формат упаковки войны и не поддерживает Fat Jar, что также вызвано этим.
Проблемы с возвратной стоимостью getResource ("") и getResources ("")
Семантика getresource («») - вернуть первый URL -адрес URL -адреса класса. Много раз пользователи думают, что это их собственный класс -каталог или URL JAR.
Но на самом деле, поскольку ClassLoader загружает список URL-адресов, он случайный, что связано с реализацией ОС низкого уровня, и он не может гарантировать, что порядок URL-адресов одинаков. Следовательно, результат, возвращаемый GetResource («»), часто отличается.
Тем не менее, многие библиотеки или приложения полагаются на этот код для поиска сканирующих ресурсов, чтобы они не будут работать в рамках Spring Boot.
Кроме того, стоит отметить, что Spring Boot работает в трех разных формах, и результаты, возвращаемые GetResources («»), также различны. Пользователи могут самостоятельно изменить код в демо и распечатать результаты.
Короче говоря, не полагайтесь на эти два API, лучше всего разместить ресурс, чтобы найти его самостоятельно. Или непосредственно используйте механизм сканирования ресурсов, предоставленный самой пружиной.
Проблема дикой классификации, похожая на ClassPath*: **-Service.xml
Пользователь имеет несколько кодовых модулей, а несколько файлов конфигурации пружины *-service.xml размещены в разных модулях.
Если пользователь использует подстановочные знаки, такие как ClassPath*: **-Service.xml для загрузки ресурсов, очень вероятно, что он может правильно загружаться при работе в IDE, но он не может загружаться под жирной банкой.
Вы можете увидеть соответствующий анализ из собственной документации Spring:
https://docs.spring.io/spring/docs/4.3.9.Release/javadoc-api/org/springframework/core/io/support/pathmatchingresourcepatternresolver.html
ПРЕДУПРЕЖДЕНИЕ: Обратите внимание, что «ClassPath:» в сочетании с шаблонами стиля муравья будет работать только надежно с одним корневым каталогом до начала шаблона, если только фактические целевые файлы не находятся в файловой системе. Это означает, что такой шаблон, как «ClassPath:*. XML», не будет получать файлы из корня файлов JAR, а скорее только из корня расширенных каталогов. Это происходит из-за ограничения в методе JDK ClassLoader.getResources (), который возвращает только местоположения файловой системы для передачи пустой строки (указывая на потенциальные корни для поиска). Эта реализация ресурса, реализация ресурса, пытается смягчить ограничение поиска корня JAR с помощью введения UrlClassLoader и "Java.class.path" Manifest Evaluation; Однако без гарантий переносимости.
То есть при использовании ClassPath* для соответствия другим пакетам JAR должен быть слой каталога впереди, в противном случае он не будет соответствовать. Это вызвано функцией ClassLoader.getResources ().
Потому что при запуске в IDE другие модули, от которых зависит приложение, обычно являются каталогом классов, поэтому обычно нет проблем.
Однако при работе с жирной банкой другие модули упаковываются в качестве банки и помещаются под ботинок/LIB, поэтому в настоящее время дикое распределение потерпит неудачу.
Суммировать
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.