Prefacio
Para obtener un análisis del principio de inicio de Spring Boot en sí, consulte: http://www.vevb.com/article/141478.htm
La relación de herencia de cargador de clases en Spring Boot puede ejecutar la demostración que se proporciona a continuación y ejecutarla en diferentes escenarios. Puede conocer la relación de herencia de carga de clases de las aplicaciones de arranque de primavera en diferentes escenarios.
https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-classloader-context
Hay tres situaciones:
En el IDE, la función de ejecución principal ejecuta directamente el cargador de clases de Spring es directamente SystemClassLoader. Las URL de clase de clase contienen todos los frascos y su propio objetivo/clases
========= Spring Boot Aplicación ClassLoader URLS ================
URLS de ClassLoader: Sun.misc.launcher$appclassloader@2a139a55
Archivo:/usuarios/hengyunabc/code/java/spring-boot-inside/demo-classloader-Context/target/classes/
Archivo: /users/hengyunabc/.m2/repository/org/springframework/cloud/spring-cloud-starter/1.1.9.release/spring-cloud-starter-1.1.9.release.jar
Archivo: /users/hengyunabc/.m2/repository/org/springframework/boot/spring-boot-starter/1.4.7.release/spring-boot-starter-1.4.7.release.jar
...
Corre como jarra gorda
MVN Clean PackageJava -Jar Target/Demo-ClassLoader-Context-0.0.1-Snapshot.jar
El cargador de clases que ejecuta la función principal de la aplicación es el lanzamiento de ClassLoader, y su padre es SystemClassLoader.
========== ClassLoader Tree ================
org.springframework.boot.loader.launchedurlclassloader@1218025c
- sun.misc.launcher$appclassloader@6bc7c054
- sun.misc.launcher$extclassloader@85ede7b
Y LaunchedURLClassLoader的urls son BOOT-INF/classes!/ En fat jar y todos los frascos en el boot-inf/lib.
========= Spring Boot Aplicación ClassLoader URLS ================
URLS de ClassLoader: org.springframework.boot.loader.launchedurlclassloader@1218025c
jar: archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar!/boot-inf/classes!/
jar: archivo: /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: archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar! /bootinf/lib/spring-web-4.3.9.release.jar!//////////jar
...
Las URL de SystemClassLoader son demo-classloader-context-0.0.1-SNAPSHOT.jar en sí.
========== Sistema URLS de carga de clases =================
URLS de ClassLoader: Sun.misc.launcher$appclassloader@6BC7C054
Archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar
Ejecutar como directorio descomprimido
MVN Clean Packagecd Targetunzip Demo-ClassLoader-Context-0.0.1-Snapshot.jar -D Democd DemoJava org.springframework.boot.loader.propertieslauncher
El cargador de clases que ejecuta la función principal de la aplicación es LaunchedURLClassLoader , y su padre es SystemClassLoader .
========== ClassLoader Tree ================
org.springframework.boot.loader.launchedurlclassloader@4aa298b7
- sun.misc.launcher$appclassloader@2a139a55
- sun.misc.launcher$extclassloader@1b6d3586
Las URL del LaunchedURLClassLoader son los paquetes JAR por debajo de BOOT-INF/classes/ y /BOOT-INF/lib/ en el directorio de descompresión.
========= Spring Boot Aplicación ClassLoader URLS ================
URLS de ClassLoader: org.springframework.boot.loader.launchedurlclassloader@4aa298b7
Archivo:/Users/Hengyunabc/Code/Java/Spring-Boot-Inside/Demo-ClassLoader-Context/Target/Demo/Boot-Inf/Classes/
jar: archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/bootinf/lib/bcpkix-jdk15on-1.55.jar!/
jar: archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/bootinf/lib/bcprov-jdk15on-1.55.Jar!
jar: archivo: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/bootinf/lib/classmate-1.3.3.jar!/
Las URL de SystemClassLoader solo tienen el directorio actual:
========== Sistema URLS de carga de clases =================
URLS de ClassLoader: Sun.misc.launcher$appclassloader@2a139a55
Archivo:/usuarios/hengyunabc/code/java/spring-boot-inside/demo-classloader-Context/target/demo/
De hecho, hay otras dos formas de ejecutar: mvn spring-boot:run y mvn spring-boot:run -Dfork=true , pero rara vez se usa y no se discutirá por separado. Si te sientes interesado, puedes correr solo.
Resumen de la relación de herencia de ClassLoader en Spring Boot
Cuando la función principal se ejecuta en el IDE, solo hay un cargador de clases, es decir, SystemClassLoader
Cuando se ejecuta como jarra gordia, hay un laguete de lanzamiento de ClassSclass cuyo padre es SystemClassLoader
Las URL de LaunchedUrlClassLoader son los frascos en Boot-Inf/classes y Boot-Inf/Lib en frascos de grasa. Las URL de SystemClassLoader son frascos de grasa.
Al ejecutar el directorio descomprimido, es similar a Fat Jar, pero la URL está en forma de directorio. El formato de directorio tendrá una mejor compatibilidad.
Versiones de arranque de primavera 1.3. y 1.4.
En Spring Boot 1.3.* Versión
La clase de cargador de arranque de primavera se coloca en el frasco de grasa
Los cambios de la estructura de empaque de Spring Boot 1.4 fueron introducidos por este comodidad
https://github.com/spring-projects/spring-boot/commit/87fe0b2adeef85c842c009bfeebac1c84af8a5d7
La intención original de esta confirmación es simplificar la relación de herencia del cargador de clases, implementar el LockedRclassLoader de una manera intuitiva de primera manera y al mismo tiempo, la estructura de empaque está más cerca de la aplicación tradicional del paquete de guerra.
Sin embargo, este cambio causó muchos problemas complejos. De lo anterior, analizamos la relación de herencia de la cargadora de clases un poco mareada.
Algunos impactos de la relación de herencia de cargador de clases actual
Hay muchos usuarios que pueden encontrar que algún código funciona bien en el IDE pero no funciona cuando realmente se implementa. Muchas veces es causada por la estructura del cargador de clases. Aquí hay algunos casos.
Demo.jar!/Boot-Inf/classes!/De esta manera la URL no funciona
Debido a que Spring Boot extiende el protocolo de JAR estándar, lo que le permite admitir Jar de múltiples capas en JAR y directorio en JAR. Consulte el análisis del principio de inicio de la aplicación de arranque de primavera
Aunque habrá Jar en JAR en Spring Boot 1.3, algún código relativamente robusto puede manejar esta situación, como Tomcat8, admite JAR en JAR.
Sin embargo, la mayoría del código no admitirá múltiples URL como demo.jar!/BOOT-INF/classes!/ , Por lo que en Spring Boot1.4, muchos códigos de biblioteca no serán válidos.
Problemas de recursos bajo Demo.jar!/Meta-Inf/Recursos
En la especificación Servlet 3.0, las aplicaciones pueden colocar recursos estáticos bajo meta-INF/recursos, y el contenedor de servlet admitirá la lectura. Pero a partir de los resultados de herencia anteriores, podemos encontrar un problema:
Esto crea algunos fenómenos extraños:
Además, el ejemplo oficial de JSSP de arranque de primavera solo admite el formato de envasado de guerra y no admite Fat Jar, que también es causado por esto.
Problemas con el valor de retorno de GetResource ("") y GetResources ("")
La semántica de GetResource ("") es devolver la primera URL de las URL de cargadores de clases. Muchas veces los usuarios piensan que este es su propio directorio de clase, o la URL de JAR.
Pero de hecho, debido a que el cargador de clases carga la lista de URLS, es aleatoria, que está relacionada con la implementación de bajo nivel de OS, y no puede garantizar que el orden de las URL sea el mismo. Por lo tanto, el resultado devuelto por GetResource ("") a menudo es diferente.
Sin embargo, muchas bibliotecas o aplicaciones dependen de este código para ubicar los recursos de escaneo, para que no funcionen bajo el arranque de primavera.
Además, vale la pena señalar que el arranque de primavera se ejecuta en tres formas diferentes, y los resultados devueltos por GetResources ("") también son diferentes. Los usuarios pueden cambiar el código en la demostración por sí mismos e imprimir los resultados.
En resumen, no confíe en estas dos API, es mejor colocar un recurso para ubicarlo usted mismo. O usar directamente el mecanismo de escaneo de recursos proporcionado por Spring.
Problema de clasificación salvaje similar a classpath*: **-Service.xml
El usuario tiene módulos de código múltiples, y múltiples archivos de configuración de resorte múltiples *-Service.xml se colocan en diferentes módulos.
Si un usuario usa comodines como classpath*: **-Service.xml para cargar recursos, es muy probable que pueda cargarse correctamente cuando se ejecuta en el IDE, pero no puede cargarse debajo del frasco de grasa.
Puede ver el análisis relevante de la propia documentación de Spring:
https://docs.spring.io/spring/docs/4.3.9.release/javadoc-api/org/springframework/core/io/support/pathmatchingresourceepatternresolver.html
ADVERTENCIA: Tenga en cuenta que "classpath:" cuando se combina con patrones de estilo hormiga solo funcionará de manera confiable con al menos un directorio raíz antes de que comience el patrón, a menos que los archivos de destino reales residan en el sistema de archivos. Esto significa que un patrón como "classpath:*. Xml" no recuperará archivos de la raíz de los archivos jar, sino solo de la raíz de los directorios expandidos. Esto se origina en una limitación en el método JDK ClassLoader.getResources () que solo devuelve las ubicaciones del sistema de archivos para una cadena vacía aprobada (indicando posibles raíces para buscar). Esta implementación de recursos de recursos está tratando de mitigar la limitación de búsqueda de la raíz de jar a través de la introducción de UrlClassLoader y la evaluación del manifiesto "java.class.path"; Sin embargo, sin garantías de portabilidad.
Es decir, cuando se usa classpath* para que coincida con otros paquetes JAR, debe haber una capa de directorio en el frente, de lo contrario no coincidirá. Esto es causado por la función ClassLoader.getResources ().
Porque cuando se ejecuta en el IDE, los otros módulos de los que depende de la aplicación generalmente son un directorio de clases, por lo que generalmente no hay problema.
Sin embargo, cuando se ejecuta con frasco de grasa, otros módulos se empaquetan como un frasco y se colocan bajo Boot-Inf/Lib, por lo que la distribución salvaje fallará en este momento.
Resumir
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.