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
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.0Main-Class: org.springframework.boot.loader.JarLauncherStart-Class: top.wisely.springasync.SpringAsyncApplicationSpring-Boot-Version: 2.7.2Spring-Boot-Classes: BOOT-INF/classes/Spring-Boot-Lib: BOOT-INF/lib/Spring-Boot-Classpath-Index: BOOT-INF/classpath.idxSpring-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 啟動應用。