淺析Spring Boot中的spring-boot-load模塊
一、前言
正常情況下classloader只能找到j(luò)ar里面當(dāng)前目錄或者文件類里面的*.class文件。為了能夠加載嵌套jar里面的資源之前都是把嵌套jar里面的class文件和應(yīng)用的class文件打包為一個(gè)jar,這樣就不存在嵌套jar了,但是這樣做就不能很清晰的知道應(yīng)用到底依賴了哪些東西,哪些是應(yīng)用自己的,另外多個(gè)jar里面的class可能內(nèi)容不一樣但是文件名卻一樣。springboot中spring-boot-loader就是為優(yōu)雅解決這個(gè)問(wèn)題而誕生的。
spring-boot-loader模塊允許我們使用java -jar archive.jar運(yùn)行包含嵌套依賴jar的jar或者war文件,它提供了三種類啟動(dòng)器 (JarLauncher, WarLauncher and PropertiesLauncher),這些類啟動(dòng)器的目的一樣都是為了能夠加載嵌套在jar里面的資源(比如class文件,配置文件等)。[Jar|War]Launcher固定去查找當(dāng)前jar的lib目錄里面的嵌套jar文件里面的資源。
二、spring-boot-loader模塊提供的jar目錄結(jié)構(gòu)
Springboot中jar文件格式固定如下:
archive.jar | +-META-INF(1) | +-MANIFEST.MF +-org(2) | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-com(3) | +-mycompany | + project | +-YouClasses.class +-lib(4) +-dependency1.jar +-dependency2.jar
- 結(jié)構(gòu)(1)jar文件中MANIFEST.MF文件存放處
- 結(jié)構(gòu)(2) Spring-boot-loader本身需要的class放置處
- 結(jié)構(gòu)(3) 應(yīng)用本身的文件放置處
- 結(jié)構(gòu)(4)應(yīng)用依賴的jar固定放到lib目錄。
那么spring-boot是如何去按照這個(gè)結(jié)構(gòu)加載資源那?
- 首先在打包時(shí)候會(huì)使用spring-boot-maven-plugin插件重寫打成的jar文件,會(huì)設(shè)置META-INF/MANIFEST.MF中的
Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.mycompany.project.MyApplication
并拷貝spring-boot-loader包里面的class文件到結(jié)構(gòu)(2),應(yīng)用依賴拷貝到(4)應(yīng)用類拷貝到(3)
- 通過(guò)java -jar archive.jar 運(yùn)行時(shí)候Launcher會(huì)去加載JarLauncher類并執(zhí)行其中的main函數(shù),JarLauncher主要關(guān)心構(gòu)造一個(gè)合適的URLClassLoader加載器用來(lái)調(diào)用我們應(yīng)用程序(MyApplication)的main方法。
三、spring-boot-maven-plugin插件打包流程分析
注:這里需要思考下為何要拷貝本來(lái)應(yīng)該放入到lib里面的spring-boot-loader.jar里面的class到結(jié)構(gòu)(2)?
四、JarLauncher執(zhí)行流程分析
看完這個(gè)流程在分析下第三節(jié)留的問(wèn)題,如流程圖首先使用Appclassloader加載了JarLauncher類并創(chuàng)建了LaunchedURLClassLoader類,而LaunchedURLClassLoader是屬于spring-boot-loader.jar包里面的,而Appclassloader是普通的加載器不能加載嵌套的jar里面的文件,所以如果把spring-boot-loader.jar放到lib 目錄下,Appclassloader將找不到LaunchedURLClassLoader。所以在打包時(shí)候
拷貝本來(lái)應(yīng)該放入到lib里面的spring-boot-loader.jar里面的class到結(jié)構(gòu)(2)。
五、總結(jié)
spring-boot-load模塊通過(guò)自定義jar包結(jié)構(gòu)自定義類加載器優(yōu)雅的實(shí)現(xiàn)了嵌套jar資源的加載,通過(guò)打包時(shí)候重新設(shè)置啟動(dòng)類和組織jar結(jié)構(gòu),通過(guò)運(yùn)行時(shí)設(shè)置自定義加載器來(lái)實(shí)現(xiàn)嵌套jar資源加載。
相關(guān)文章
使用Filter過(guò)濾器中訪問(wèn)getSession()要轉(zhuǎn)化
這篇文章主要介紹了使用Filter過(guò)濾器中訪問(wèn)getSession()要轉(zhuǎn)化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java基礎(chǔ)知識(shí)精通塊作用域與條件及switch語(yǔ)句
塊(block,即復(fù)合語(yǔ)句)是指由若干條 Java 語(yǔ)句組成的語(yǔ)句,并由一對(duì)大括號(hào)括起來(lái)。塊確定了變量的作用域。一個(gè)塊可以嵌套在另一個(gè)塊中;條件語(yǔ)句、switch語(yǔ)句是我們常見(jiàn)會(huì)用到的結(jié)構(gòu),感興趣的朋友來(lái)看看吧2022-04-04編寫調(diào)用新浪微博API的Java程序來(lái)發(fā)送微博
這篇文章主要介紹了編寫調(diào)用新浪微博API的Java程序來(lái)發(fā)送微博的方法,只是展示了一個(gè)基本的程序框架而非一個(gè)完整的圖形化軟件:)需要的朋友可以參考下2015-11-11SpringCloud對(duì)服務(wù)內(nèi)某個(gè)client進(jìn)行單獨(dú)配置的操作步驟
我們的微服務(wù)項(xiàng)目用的是springCloud,某個(gè)微服務(wù)接口因?yàn)閿?shù)據(jù)處理量大,出現(xiàn)了接口超時(shí)的情況,我們需要單獨(dú)修改這一個(gè)feignClient的超時(shí)時(shí)間,所以本文介紹了SpringCloud對(duì)服務(wù)內(nèi)某個(gè)client進(jìn)行單獨(dú)配置的操作步驟,需要的朋友可以參考下2023-10-10SpringBoot框架實(shí)現(xiàn)切換啟動(dòng)開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境
這篇文章主要介紹了SpringBoot框架實(shí)現(xiàn)切換啟動(dòng)開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java HtmlEmail 郵件發(fā)送的簡(jiǎn)單實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇Java HtmlEmail 郵件發(fā)送的簡(jiǎn)單實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06SpringBoot 如何實(shí)時(shí)刷新靜態(tài)文件
這篇文章主要介紹了SpringBoot如何實(shí)時(shí)刷新靜態(tài)文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12