Vorwort
Eine Analyse des Startprinzips des Spring -Bootes selbst finden Sie unter: http://www.vevb.com/article/141478.htm
Die Vererbungsbeziehung der Klassenlader im Spring Boot kann die unten angegebene Demo ausführen und in verschiedenen Szenarien ausführen. Sie können die Vererbungsbeziehung der Klassenlader in Spring -Boot -Anwendungen in verschiedenen Szenarien kennen.
https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-classloader-context
Es gibt drei Situationen:
In der IDE wird in der Hauptfunktion direkt den Klassenloader von Spring direkt ausgelegt. URLs des Classloaders enthalten alle Gläser und ihr eigenes Ziel/ihre eigenen Klassen
========= Spring Boot Application Classloader URLS ===============
CLASSOADER URLS: sun.misc.launcher$appclassloader@2a139a55
Datei:/user/hengyunabc/code/java/spring-boot-i-Inside/Demo-Classloader-context/target/classes/
Datei: /users/hengyunabc/.m2/repository/org/springframework/cloud/spring-cloud-starter/1.1.9.release/spring-cloud-starter-1.1.9.release.jar
Datei: /users/hengyunabc/.m2/repository/org/springframework/boot/spring-boot-starter/1.4.7.release/spring-boot-starter-1.4.release.jar
...
Rennen als fettes Glas
MVN Clean Packagejava -Jar Target/Demo-Classloader-Context-0.0.1-Snapshot.jar
Der Klassenloader, der die Hauptfunktion der Anwendung ausführt, ist der Laderader für die Anwendung und sein übergeordnetes SYLECASSLOADER.
========== Classloader Tree ===============
org.springframework.boot.loader.launchedurlclassloader@1218025c
- sun.misc.launcher$appclassloader@6bc7c054
- sun.misc.launcher $EXTCLASLOADER@85ede7b
Und LaunchedURLClassLoader的urls sind BOOT-INF/classes!/ Verzeichnis im fat jar und alle Gläser im Boot-Inf/lib.
========= Spring Boot Application Classloader URLS ===============
Classloader -URLs: org.springframework.boot.loader.launchedurlclassloader@1218025c
JAR: Datei: /Users/Hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo-classloader-context-0.0.1-snapshot.jar!/boot-inf/classs!/klassen!
JAR: Datei: /Users/Hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo-clader-context-0.0.1-snapshot.jar! /boot-inf/spring-boot-1.4.4.7.relase.jar!/////rie.7.4.7.relase.jar!/
JAR: Datei: /Users/Hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo-classloader-context-0.0.1-snapshot.jar! /boot-inf/spring-web-43.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.jar!///boot-inf/spring-web-b-
...
Die URLs von SystemClassLoader sind demo-classloader-context-0.0.1-SNAPSHOT.jar selbst.
========== System Classloader URLs =======================================
CLASSOADER -URLS:
Datei: /users/hengyunabc/code/java/spring-boot-inside/demo-classloade-context/target/demo-classloader-context-0.0.1-snapshot.jar
Laufen Sie als dekomprimiertes Verzeichnis
MVN Clean Packagecd Targetunzip Demo-Classloader-Context-0.0.1-Snapshot.jar -d Demojava org.springframework.boot.loader.propertieSlaunchner
Der Klassenloader, der die Hauptfunktion der Anwendung ausführt, ist LaunchedURLClassLoader und sein übergeordnetes SystemClassLoader .
========== Classloader Tree ===============
org.springframework.boot.loader.launchedurlclassloader@4aa298b7
- sun.misc.launcher$appclassloader@2a139a55
- sun.misc.launcher $EXTCLASLOADER@1B6D3586
Die URLs des LaunchedURLClassLoader sind die JAR-Pakete unter BOOT-INF/classes/ und /BOOT-INF/lib/ im Dekompressionsverzeichnis.
========= Spring Boot Application Classloader URLS ===============
Classloader -URLs: org.springframework.boot.loader.launchedurlclassloader@4aa298b7
Datei:/user/hengyunabc/code/java/spring-boot-i-Inside/Demo-Classloader-Context/Target/Demo/Boot-Inf/Klassen/
JAR: Datei: /Users/Hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo/boot-inf/lib/bcpkix-jdk15on-1.55.jar!/////////
JAR: Datei: /Users/Hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo/boot-inf/lib/bcprov-jdk15on-1.55.jar!////////
JAR: Datei: /Users/hengyunabc/code/java/spring-boot-inside/demo-clader-context/target/demo/boot-inf/lib/classmate-1.3.jar!//////////
Die URLs von SystemClassLoader haben nur das aktuelle Verzeichnis:
========== System Classloader URLs =======================================
CLASSOADER URLS: sun.misc.launcher$appclassloader@2a139a55
Datei:/user/hengyunabc/code/java/spring-boot-i-Inside/Demo-Classloader-Context/Target/Demo/Demo/
Tatsächlich gibt es zwei andere Möglichkeiten zum Laufen: mvn spring-boot:run und mvn spring-boot:run -Dfork=true , aber es wird selten verwendet und wird nicht separat diskutiert. Wenn Sie sich interessiert fühlen, können Sie alleine herunterlaufen.
Zusammenfassung der Erbschaftsbeziehung von Classloader im Spring Boot
Wenn die Hauptfunktion in der IDE ausgeführt wird, gibt es nur einen Klassenloader, dh Systemclassloader
Beim Ausführen als Fat Jar gibt es einen LOADER für den Ladern von LOWNEDURLAS, dessen übergeordnetes Systemclassloader ist
Die URLs von StartedurlClassloader sind die Gläser unter Boot-Inf/Klassen und Boot-Inf/lib in fetten Gläser. Die URLs von SystemClassloader sind selbst fette Gläser.
Beim Ausführen des unzippierten Verzeichnisses ähnelt es dem Fat Jar, aber die URL ist in Form eines Verzeichnisses. Das Verzeichnisformat hat eine bessere Kompatibilität.
Federschuhversionen 1.3. und 1.4.
In Spring Boot 1.3.* Version
Die Feder -Boot -Lader -Klasse wird in das fette Glas platziert
Die Verpackungsstrukturänderungen von Spring Boot 1.4 wurden von diesem Commit eingeführt
https://github.com/spring-projects/spring-boot/commit/87fe0b2adeef85c842c009bfeebac1c84af8a5d7
Die ursprüngliche Absicht dieses Commits ist es, die Vererbungsbeziehung des Klassenloaders zu vereinfachen, den LOWNEDURLCLASSOLOADER auf intuitive übergeordnete Weise zu implementieren, und gleichzeitig liegt die Verpackungsstruktur näher an der traditionellen Kriegspaketanwendung.
Diese Änderung verursachte jedoch viele komplexe Probleme. Aus dem obigen analysierten wir die Vererbungsbeziehung der Klassenlader ein wenig schwindelig.
Einige Auswirkungen der aktuellen Vererbungsbeziehung der Klassenloader
Es gibt viele Benutzer, die möglicherweise feststellen, dass ein Code in der IDE gut ausgeführt wird, aber beim Tatsachen nicht funktioniert. Oft wird es durch die Struktur des Klassenloaders verursacht. Hier sind einige Fälle.
Demo.jar!/Startinf/Klassen!/Auf diese Weise funktioniert die URL nicht
Da Spring Boot das Standard-JAR-Protokoll erweitert und es ihm ermöglicht, mehrschichtig in Glas und Verzeichnis in Jar zu unterstützen. Siehe Analyse des Prinzips zum Start von Spring Boot Application
Obwohl es in Spring Boot 1.3 Jar in Jar geben wird, kann ein relativ robuster Code diese Situation bewältigen, wie z. B. Tomcat8 selbst unterstützt Jar in Glas.
Der größte Teil des Codes unterstützt jedoch nicht mehrere URLs wie demo.jar!/BOOT-INF/classes!/ , So dass in Spring Boot1.4 viele Bibliothekscodes ungültig sind.
Ressourcenprobleme unter Demo.jar!/Meta-inf/Ressourcen
In der Diener 3.0-Spezifikation können Anwendungen statische Ressourcen unter Meta-Inf/Ressourcen aufstellen, und der Servlet-Container unterstützt das Lesen. Aus den obigen Vererbungsergebnissen können wir jedoch ein Problem finden:
Dies schafft einige seltsame Phänomene:
Darüber hinaus unterstützt das offizielle JSSP -Beispiel für Spring Boot nur das Verpackungsformat des Krieges und unterstützt nicht fettes Glas, das auch dadurch verursacht wird.
Probleme mit dem Rückgabewert von GetResource ("") und GetResources ("")
Die Semantik von GetResource ("") besteht darin, die erste URL der Classloader -URLs zurückzugeben. Oft denken die Benutzer, dass dies ein eigenes Klassenverzeichnis oder die JAR -URL ist.
Da Classloader die URLS-Liste lädt, ist sie jedoch zufällig, was sich auf die Implementierung von Betriebssystem auf niedriger Ebene bezieht, und es kann nicht garantieren, dass die Reihenfolge der URLs gleich ist. Daher ist das von GetResource ("") zurückgegebene Ergebnis oft unterschiedlich.
Viele Bibliotheken oder Anwendungen verlassen sich jedoch auf diesen Code, um Scan -Ressourcen zu finden, damit sie nicht unter Spring Boot arbeiten.
Darüber hinaus ist es erwähnenswert, dass Spring Boot in drei verschiedenen Formen läuft und die von getResources ("") zurückgegebenen Ergebnisse ebenfalls unterschiedlich sind. Benutzer können den Code in der Demo selbst ändern und die Ergebnisse drucken.
Kurz gesagt, verlassen Sie sich nicht auf diese beiden APIs. Es ist am besten, eine Ressource zu platzieren, um sie selbst zu finden. Oder verwenden Sie direkt den Ressourcen -Scanmechanismus, der von der Feder selbst bereitgestellt wird.
Wildklassifizierungsproblem ähnlich wie der Klassenpfad*: **-service.xml
Der Benutzer verfügt über mehrere Codemodule, und mehrere *-Service.xml-Federkonfigurationsdateien werden unter verschiedenen Modulen platziert.
Wenn ein Benutzer Wildcards wie ClassPath*: **-service.xml verwendet, um Ressourcen zu laden, ist es sehr wahrscheinlich, dass er beim Ausführen in der IDE korrekt geladen werden kann, aber nicht unter das Fettglas geladen wird.
Sie können die relevante Analyse aus der eigenen Dokumentation von Spring sehen:
https://docs.spring.io/spring/docs/4.9.9.release/javadoc-api/org/springframework/core/io/support/pathmatchingresourcePatternresolver.html
Warnung: Beachten Sie, dass „ClassPath“ in Kombination mit Ameisenmustern nur zuverlässig mit mindestens einem Root-Verzeichnis funktioniert, bevor das Muster startet, es sei denn, die tatsächlichen Zieldateien befinden sich im Dateisystem. Dies bedeutet, dass ein Muster wie „ClassPath:*. XML“ Dateien nicht aus dem Stamm von JAR -Dateien, sondern nur aus dem Stamm der erweiterten Verzeichnisse abgerufen. Dies stammt aus einer Einschränkung in der Methode der JDK-Klasse. Diese Implementierung von RessourcenpeufperResolver versucht, die Einschränkung der Jar -Root -Looke -Einführung durch die Einführung von UrlClassloader und die Manifestbewertung von "Java.Class.Path" zu mildern. ohne Portabilitätsgarantien.
Das heißt, wenn es ClassPath* verwendet, um andere JAR -Pakete zu entsprechen, muss es eine Verzeichnisschicht vor Ort geben, da sie sonst nicht übereinstimmt. Dies wird durch die Funktion classloader.getResources () verursacht.
Denn beim Ausführen in der IDE sind die anderen Module, von denen die Anwendung abhängt, normalerweise ein Klassenverzeichnis, sodass normalerweise kein Problem besteht.
Beim Laufen mit fettem Glas werden andere Module jedoch als Glasverpackt verpackt und unter Boot-INF/LIB gestellt, sodass die Wildverteilung zu diesem Zeitpunkt fehlschlägt.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.