1. Preface
Under normal circumstances, the classloader can only find the *.class file in the current directory or file class in the jar. In order to load the resources in the nested jar, the class file in the nested jar and the class file of the application are packaged into a jar, so that there is no nested jar. However, in doing so, you cannot clearly know what the application depends on and which ones are the application itself. In addition, the class content in multiple jars may be different but the file names are the same. Spring-boot-loader in springboot was born to solve this problem gracefully.
The spring-boot-loader module allows us to use java -jar archive.jar to run jar or war files containing nested dependencies. It provides three types of launchers (JarLauncher, WarLauncher and PropertiesLauncher). The purpose of these class launchers is to be able to load resources nested in the jar (such as class files, configuration files, etc.). [Jar|War] Launcher fixedly searches for resources in nested jar files in the lib directory of the current jar.
2. The jar directory structure provided by the spring-boot-loader module
The jar file format in Springboot is fixed as follows:
archive.jar | +-META-INF(1) | +-MANIFEST.MF +-org(2) | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-com(3) | +-mycompany | + project | +-YouClasses.class +-lib(4) +-dependency1.jar +-dependency2.jar
So how does spring-boot load resources according to this structure?
Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.mycompany.project.MyApplication
And copy the class file in the spring-boot-loader package to the structure (2), copy the application dependency to (4) copy the application class to (3)
3. Analysis of spring-boot-maven-plugin plug-in packaging process
Note: Here we need to think about why we need to copy the class to structure (2) that should have been put into the spring-boot-loader.jar that we should have put into lib?
4. JarLauncher execution process analysis
After reading this process, we will analyze the problems left in the third section. For example, the flowchart first uses Appclassloader to load the JarLauncher class and create the LaunchedURLClassLoader class. The LaunchedURLClassLoader belongs to the spring-boot-loader.jar package, and the Appclassloader is an ordinary loader that cannot load the files in the nested jar. Therefore, if spring-boot-loader.jar is placed in the lib directory, the Appclassloader will not find the LaunchedURLClassLoader. So when packing
Copy the class to structure (2) that should have been put into the spring-boot-loader.jar in lib.
5. Summary
The spring-boot-load module elegantly implements the loading of nested jar resources through a custom jar package structure. By resetting the startup class and organization jar structure during packaging, and setting a custom loader at runtime to achieve nested jar resources.