SpringBoot使用SpringBootGradlePlugin或者SpringBootMavenPlugin将程序打包成可以独立运行的jar包的。SpringBoot使用SpringBootLoader通过java-jar来启动jar包。我们来解压一下SpringBoot的jar包(jar其实
Spring Boot使用Spring Boot Gradle Plugin或者Spring Boot Maven Plugin将程序打包成可以独立运行的jar包的。
Spring Boot使用Spring Boot Loader通过java -jar 来启动jar包。
我们来解压一下Spring Boot的jar包(jar其实是一个zip文件)
我们可以看到解压的目录下有三个子目录: BOOT-INF ,META-INF ,org
复制 example.jar
|
+- META- INF
| +- MANIFEST.MF
+- org
| +- springframework
| +- boot
| +- loader
| +-< spring boot loader classes>
+- BOOT- INF
+- classes
| +- mycompany
| +- project
| +- YourClasses.class
+- lib
+- dependency1.jar
+- dependency2.jar
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
BOOT-INF
BOOT-INF/classes : 应用程序的classes文件BOOT-INF/lib : 内嵌依赖包BOOT-INF/classpath.idx : jar包添加到classpath的顺序BOOT-INF/layers.idx : 允许将 jar 拆分为逻辑层以创建Docker/OCI镜像
META-INF
META-INF/MANIFEST.MF : 有关jar中包含的文件的信息
org
Spring Boot Loader的classes
探索Spring Boot的魔法 我们将通过一步一步的jar包启动步骤来分析这个过程:
java -jar 在 META-INF/MANIFEST.MF文件中寻找可执行jar包的入口类:
复制 Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: top.wisely.springasync.SpringAsyncApplication
Spring-Boot-Version: 2.7.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Main-Class: org.springframework.boot.loader.JarLauncher 是主入口类.JarLauncher extends ExecutableArchiveLauncher 并且ExecutableArchiveLauncher extends Launcher JarLauncher 的main方法:
复制 public class JarLauncher extends ExecutableArchiveLauncher {
//...
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
//...
}
所以真正的 launch(args) 方法在 Launcher 类中:
复制 public abstract class Launcher {
protected void launch(String[] args) throws Exception {
if (!isExploded()) {
JarFile.registerUrlProtocolHandler();
}
ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator()); //①
String jarMode = System.getProperty("jarmode");
String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass(); //②
launch(args, launchClass, classLoader); //③
}
}
① classLoader - 创建LaunchedURLClassLoader 实例. 所有的 BOOT-INF/classes 和 BOOT-INF/jar classes 都是由 LaunchedURLClassLoader 加载。
② launchClass - 从 META-INF/MANIFEST.MF 获取Start-Class。
③ 使用 args ,launchClass ,classLoader 启动应用。
文章出自:爱科学的卫斯理,作者:汪云飞。如有转载本文请联系爱科学的卫斯理今日头条号。