Spring?Boot?打包成Jar包運(yùn)行原理分析
SpringBoot打包
相比與傳統(tǒng)的Java打包方式,使用SpringBoot打包插件打包成jar包后,可以直接使用java -jar
運(yùn)行SpringBoot項(xiàng)目,本篇就來(lái)分析一下運(yùn)行的原理。
SpringBoot打包插件
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
打包完后會(huì)生成兩個(gè)文件,一個(gè)***.jar
和***.jar.original
.jar
文件是SpringBoot打包后生成的文件,.jar.original
是用原生方式打包生成的文件,對(duì)比一下兩個(gè)的區(qū)別
.jar.original文件
.jar文件
.jar.original
就是普通的jar打包的結(jié)構(gòu),這里主要看.jar
文件的結(jié)構(gòu):
META-INFO目錄:META-INFO/MANIFEST.MF里包含了jar包的元數(shù)據(jù),包含了項(xiàng)目的啟動(dòng)類等信息.
org目錄:該目錄下包含的是啟動(dòng)項(xiàng)目的一些類,啟動(dòng)的過(guò)程就在這個(gè)包里。
BOOT-INFO目錄:本地項(xiàng)目的代碼(BOOT-INF/classes),以及所需的以依賴(BOOT-INFO/lib)
重點(diǎn) META-INFO/MANIFEST.MF
Manifest-Version: 1.0 Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Implementation-Title: demo Implementation-Version: 0.0.1-SNAPSHOT Spring-Boot-Layers-Index: BOOT-INF/layers.idx Start-Class: com.example.demo.DemoApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Build-Jdk-Spec: 1.8 Spring-Boot-Version: 2.4.5 Created-By: Maven Jar Plugin 3.2.0 Main-Class: org.springframework.boot.loader.JarLauncher
這里有幾個(gè)重點(diǎn)的字段
- Main-Class :jar包啟動(dòng)類,這是java規(guī)定的字段,存在這個(gè)字段的情況下, 在
java -jar
時(shí),jar包才會(huì)運(yùn)行起來(lái) - Start-Class:本地項(xiàng)目的啟動(dòng)類
- Spring-Boot-Classes:加載應(yīng)用類的入口
- Spring-Boot-Lib:項(xiàng)目所需的依賴
有了Main-Class啟動(dòng)類,那就直接進(jìn)入到JarLauncher
里查看運(yùn)行的過(guò)程
public static void main(String[] args) throws Exception { (new JarLauncher()).launch(args); }
在JarLauncher
的main
方法里調(diào)用了launch
方法,launch
方法的具體實(shí)現(xiàn)在JarLauncher
的抽象父類Launcher
中實(shí)現(xiàn)
protected void launch(String[] args) throws Exception { if (!this.isExploded()) { JarFile.registerUrlProtocolHandler(); } ClassLoader classLoader = this.createClassLoader(this.getClassPathArchivesIterator()); String jarMode = System.getProperty("jarmode"); String launchClass = jarMode != null && !jarMode.isEmpty() ? "org.springframework.boot.loader.jarmode.JarModeLauncher" : this.getMainClass(); this.launch(args, launchClass, classLoader); }
首先獲取了類加載器。
然后獲取jarMode,再根據(jù)jarMode獲取launchClass,如果沒(méi)有設(shè)置jarMode,則根據(jù)getMainClass
方法獲取,getMainClass
的具體實(shí)現(xiàn)在ExecutableArchiveLauncher
中實(shí)現(xiàn)
protected String getMainClass() throws Exception { Manifest manifest = this.archive.getManifest(); String mainClass = null; if (manifest != null) { mainClass = manifest.getMainAttributes().getValue("Start-Class"); } if (mainClass == null) { throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this); } else { return mainClass; } }
在getMainClass
里獲取了MANIFEST.MF
文件里Start-Class
字段的值,也就是本地項(xiàng)目的啟動(dòng)類。
最后調(diào)用this.launch(args, launchClass, classLoader);
protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception { Thread.currentThread().setContextClassLoader(classLoader); this.createMainMethodRunner(launchClass, args, classLoader).run(); }
調(diào)用MainMethodRunner
的run()
方法
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((Object)null, this.args); }
在run()
方法里通過(guò)反射拿到了項(xiàng)目的啟動(dòng)類的main
方法,從而啟動(dòng)本地項(xiàng)目。
以上就是Spring Boot 打包成Jar包運(yùn)行的原理的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot Jar包的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)瀏覽器大文件上傳的示例詳解
文件上傳是許多項(xiàng)目都有的功能,用戶上傳小文件速度一般都很快,但如果是大文件幾個(gè)g,幾十個(gè)g的時(shí)候,上傳了半天,馬上就要完成的時(shí)候,網(wǎng)絡(luò)波動(dòng)一下,文件又要重新上傳,所以本文給大家介紹了Java實(shí)現(xiàn)瀏覽器大文件上傳的示例,需要的朋友可以參考下2024-07-07Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開(kāi)發(fā)
這篇文章主要介紹了Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開(kāi)發(fā),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10SpringBoot集成itextpdf實(shí)現(xiàn)根據(jù)模板動(dòng)態(tài)生成PDF
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何集成itextpdf實(shí)現(xiàn)根據(jù)模板動(dòng)態(tài)生成PDF,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下2024-03-03mybatis調(diào)用mysql存儲(chǔ)過(guò)程并獲取返回值方式
這篇文章主要介紹了mybatis調(diào)用mysql存儲(chǔ)過(guò)程并獲取返回值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08java后端實(shí)現(xiàn)信息分頁(yè)查詢的示例代碼
在一個(gè)頁(yè)面展示大量的用戶信息不便于觀看,因此就需要采用分頁(yè)展示的方法,本文就來(lái)為大家介紹一下java后端如何實(shí)現(xiàn)信息分頁(yè)查詢,需要的小伙伴可以參考下2023-11-11spring?aop?Pointcut?execution規(guī)則介紹
這篇文章主要介紹了spring?aop?Pointcut?execution規(guī)則,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11