SpringBoot應(yīng)用能直接運行java -jar的原因分析
首先明確一點,普通jar包是不能直接運行的,比如工具類jar
要能運行,至少得要一個main函數(shù)作為入口吧?
SpringBoot應(yīng)用確實有個main函數(shù),那么問題來了,java -jar是怎么找到這個main函數(shù)運行的?
先說答案
是因為引入了spring-boot-maven-plugin插件
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
不信?
現(xiàn)在不使用這個插件,將SpringBoot應(yīng)用打個jar包
target目錄產(chǎn)出文件如下
注意此時的jar體積為3202KB,內(nèi)容只包含了項目中的代碼和resources下的文件
嘗試java -jar運行,報錯沒有主清單屬性
這是把spring-boot-maven-plugin插件加上,再次打包
target目錄如下
jar包體積變大了!另外多出一個jar.origin,大小和之前jar包的一樣
當(dāng)然我們只需要關(guān)系jar即可
查看jar包中的內(nèi)容,不僅包含了自己寫的類(classes),還將依賴的第三方j(luò)ar包全部裝了進(jìn)來(lib),這種jar被稱為fat jar
這時使用java -jar命令,成功運行!
按照常規(guī)思路,一定是要找到main方法所在的這個類,然后去運行里面的main方法
其實,當(dāng)執(zhí)行java -jar時,會自動去找一個叫MANIFEST.MF的文件,然后根據(jù)其中的Main-Class找到入口類,并執(zhí)行其中的main方法
而SpringBoot的jar包的這個文件,就是spring-boot-maven-plugin這個插件生成的
這個文件中的內(nèi)容如下
Manifest-Version: 1.0 Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Archiver-Version: Plexus Archiver Built-By: yimin Spring-Boot-Layers-Index: BOOT-INF/layers.idx Start-Class: com.example.k8sdemo.K8sDemoApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Version: 2.6.13 Created-By: Apache Maven 3.8.8 Build-Jdk: 1.8.0_392 Main-Class: org.springframework.boot.loader.JarLauncher
好家伙,Main-Class居然不是我們自己寫的那個類
而是org.springframework.boot.loader.JarLauncher
想要查看這個類,先引入以下依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-loader</artifactId> </dependency>
JarLauncher的main函數(shù)以及方法調(diào)用如下
public static void main(String[] args) throws Exception { new JarLauncher().launch(args); } 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); } @Override protected String getMainClass() throws Exception { String mainClass = getProperty(MAIN, "Start-Class"); if (mainClass == null) { throw new IllegalStateException("No '" + MAIN + "' or 'Start-Class' specified"); } return mainClass; } protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception { Thread.currentThread().setContextClassLoader(classLoader); createMainMethodRunner(launchClass, args, classLoader).run(); } protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) { return new MainMethodRunner(mainClass, args); } public void run() throws Exception { Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader()); Method mainMethod = mainClass.getDeclaredMethod("main", String[].class); mainMethod.setAccessible(true); mainMethod.invoke(null, new Object[] { this.args }); }
總結(jié)一下就是
- 創(chuàng)建一個自定義的類加載器
LaunchedURLClassLoader
- 使用這個自定義的ClassLoader去加載我們自己寫的main方法類,這個類由MANIFEST.MF中Start-Class定義
- 反射獲取main方法,然后執(zhí)行
以上就是SpringBoot應(yīng)用能直接運行java -jar的原因分析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot直接運行java -jar的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Boot 結(jié)合 aop 實現(xiàn)讀寫分離
這篇文章主要介紹了Spring Boot 結(jié)合 aop 實現(xiàn)讀寫分離的示例,幫助大家更好的理解和使用Spring Boot框架,感興趣的朋友可以了解下2020-11-11Springboot項目通過redis實現(xiàn)接口的冪等性
這篇文章主要為大家介紹了Springboot項目通過redis實現(xiàn)接口的冪等性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12SpringCloud Gateway使用redis實現(xiàn)動態(tài)路由的方法
這篇文章主要介紹了SpringCloud Gateway使用redis實現(xiàn)動態(tài)路由的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01Java并發(fā)編程之性能、擴(kuò)展性和響應(yīng)
這篇文章主要介紹了Java并發(fā)編程之性能、擴(kuò)展性和響應(yīng),重點在于多線程應(yīng)用程序的性能問題,給性能和擴(kuò)展性下一個定義,然后再仔細(xì)學(xué)習(xí)一下Amdahl法則,感興趣的小伙伴們可以參考一下2016-02-02java微信企業(yè)號開發(fā)之發(fā)送消息(文本、圖片、語音)
這篇文章主要為大家詳細(xì)介紹了java微信企業(yè)號開發(fā)之發(fā)送消息,發(fā)送類型包括文本、圖片、語音,感興趣的小伙伴們可以參考一下2016-06-06SSH框架網(wǎng)上商城項目第21戰(zhàn)之詳解易寶支付的流程
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項目第21戰(zhàn)之易寶支付的流程,感興趣的小伙伴們可以參考一下2016-06-06