打包生成兩個jar包
ssmdemo-plus.jar 引入了相關第三方依賴。
ssmdemo-plus.jar.original 僅包含應用編譯后的本地資源
jar包的目錄結構
|—— BOOT-INF |—— classes 存放的是應用編譯后的class文件 |—— lib 存放的是應用依賴的第三方jar包文件 |——META-INF 存放應用打包信息maven坐標、pom文件和MANIFEST.MF |—— MANIFEST.MF |—— maven |—— org 目錄存放SpringBoot相關class文件 |—— springframework
使用java -jar命令執行 spring Boot 應用的可執行jar文件
會讀取META-INF/MANIFEST.MF文件的Main-Class屬性值,該值表示應用程序執行入口類
MANIFEST.MF文件內容
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Built-By: NB-20200504-3 Start-Class: com.zwh.Application Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Version: 2.2.3.RELEASE Created-By: Apache Maven 3.6.1 Build-Jdk: 1.8.0_231 Main-Class: org.springframework.boot.loader.JarLauncher
會執行org.springframework.boot.loader包下的JarLauncher的main方法
這里會做操作
JarLauncher.java public static void main(String[] args) throws Exception { (new JarLauncher()).launch(args); } Launcher.java protected void launch(String[] args) throws Exception { JarFile.registerUrlProtocolHandler(); ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives()); this.launch(args, this.getMainClass(), classLoader); }
JarFile.registerUrlProtocolHandler();
這個方法作用:
利用java url協議實現擴展原理,自定義jar協議 將org.springframework.boot.loader包 追加到java系統 屬性java.protocol.handler.pkgs中,實現自定義jar協議 參考鏈接:java 自定義通訊協議 [https://blog.csdn.net/d_x_program/article/details/75038200] java會在java.protocol.handler.pkgs系統屬性指定的包中查找與協議同名的子包和名為Handler的類, 即負責處理當前協議的URLStreamHandler實現類必須在 <包名>.<協議名定義的包> 中,並且類名稱必須為Handler 例如: org.springframework.boot.loader.jar.Handler這個類 將用於處理jar協議 這個jar協議實現作用: 參考鏈接:SpringBoot FatJar啟動原理 [https://www.cnblogs.com/jfire/p/11973093.html] springBoot在打包時候會將第三方依賴jar包打進最終的Jar,變成一個可運行的FatJar。 默認情況下,JDK提供的ClassLoader只能識別jar中的class文件以及加載classpath下的其他jar包中的class文件。 對於jar包中的jar包是無法加載的 所以spring boot 自己定義了一套URLStreamHandler實現類和JarURLConnection實現類,用來加載jar包中的jar包的class類文件
下一步
ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
創建類加載器,得到可以加載嵌套式的jar文件的類加載器
然后
調用this.launch(args, this.getMainClass(), classLoader);方法,
讀取Manifest的Start-Class屬性利用反射執行main方法完成應用程序的啟動
start-class屬性其實就是我們項目里面的Application程序