




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第SpringBoot的jar包如何啟動(dòng)的實(shí)現(xiàn)目錄一、簡(jiǎn)介二、jar包的內(nèi)部結(jié)構(gòu)三、加載過程1.使用到的一些類2.過程分析四、總結(jié)
一、簡(jiǎn)介
?使用過SprongBoot打過jar包的都應(yīng)該知道,目標(biāo)文件一般都會(huì)生成兩個(gè)文件,一個(gè)是以.jar的包,一個(gè)是.jar.original文件。那么使用SpringBoot會(huì)打出兩個(gè)包,而.jar.original的作用是什么呢?還有就是java-jar是如何將一個(gè)SpringBoot項(xiàng)目啟動(dòng),之間都進(jìn)行了那些的操作?
?其實(shí).jar.original是maven在SpringBoot重新打包之前的原始jar包,內(nèi)部只包含了項(xiàng)目的用戶類,不包含其他的依賴jar包,生成之后,SpringBoot重新打包之后,最后生成.jar包,內(nèi)部包含了原始jar包以及其他的引用依賴。以下提及的jar包都是SpringBoot二次加工打的包。
二、jar包的內(nèi)部結(jié)構(gòu)
SpringBoot打出的jar包,可以直接通過解壓的方式查看內(nèi)部的構(gòu)造。一般情況下有三個(gè)目錄。
BOOT-INF:這個(gè)文件夾下有兩個(gè)文件夾classes用來存放用戶類,也就是原始jar.original里的類;還有一個(gè)是lib,就是這個(gè)原始jar.original引用的依賴。META-INF:這里是通過java-jar啟動(dòng)的入口信息,記錄了入口類的位置等信息。org:Springbootloader的代碼,通過它來啟動(dòng)。
這里主要介紹一下/BOOT-INF/MANIFEST.MF文件
Main-Class:org.springframework.boot.loader.JarLauncher
Start-Class:.springboot.center.AuthEenterBootstrap
Main-Class:記錄了java-jar的啟動(dòng)入口,當(dāng)使用該命令啟動(dòng)時(shí)就會(huì)調(diào)用這個(gè)入口類的main方法,顯然可以看出,Springboot轉(zhuǎn)移了啟動(dòng)的入口,不是用戶編寫的xxx.xxx.BootStrap的那個(gè)入口類。
Start-Class:記錄了用戶編寫的xxx.xxx.BootStrap的那個(gè)入口類,當(dāng)內(nèi)嵌的jar包加載完成之后,會(huì)使用LaunchedURLClassLoader線程加載類來加載這個(gè)用戶編寫的入口類。
三、加載過程
1.使用到的一些類
3.1.1Archive
?歸檔文件接口,實(shí)現(xiàn)迭代器接口,它有兩個(gè)子類,一個(gè)是JarFileArchive對(duì)jar包文件使用,提供了返回這個(gè)jar文件對(duì)應(yīng)的url、或者這個(gè)jar文件的MANIFEST文件數(shù)據(jù)信息等操作。是ExplodedArchive是文件目錄的使用也有獲取這個(gè)目錄url的方法,以及獲取這個(gè)目錄下的所有Archive文件方法。
3.1.2Launcher
?啟動(dòng)程序的基類,這邊最后是通過JarLauncher#main()來啟動(dòng)。ExecutableArchiveLauncher是抽象類,提供了獲取Start-Class類路徑的方法,以及是否還有內(nèi)嵌對(duì)應(yīng)文件的判斷方法和獲取到內(nèi)嵌對(duì)應(yīng)文件集合的后置處理方法的抽象,由子類JarLauncher和WarLauncher自行實(shí)現(xiàn)。
3.1.3Spring.loader下的JarFile和JarEntry
?jarFile繼承于jar.util.jar.JarFile,JarEntry繼承于java.util.jar.JarEntry,對(duì)原始的一些方法進(jìn)行重寫覆蓋。每一個(gè)JarFileArchive都擁有一個(gè)JarFile方法,用于存儲(chǔ)這個(gè)jar包對(duì)應(yīng)的文件,而每一個(gè)JarFile都有一個(gè)JarFileEntries,JarFileEntries是一個(gè)迭代器??偟膩碚f,在解析jar包時(shí),會(huì)將jar包內(nèi)的文件封裝成JarEntry對(duì)象后由JarFile對(duì)象保存文件列表的迭代器。所以JarFileArchive和JarFileEntries之間是通過JarFile連接,二者都可以獲取到JarFile對(duì)象。
2.過程分析
從MANIFEST.MF文件中的Main-class指向入口開始。
創(chuàng)建JarLauncher并且通過它的launch()方法開始加載jar包內(nèi)部信息。
publicstaticvoidmain(String[]args)throwsException{
newJarLauncher().launch(args);
}
JarLauncher的空構(gòu)造方法時(shí)一個(gè)空實(shí)現(xiàn),剛開始看的時(shí)候還懵了一下,以為是在后續(xù)的操作中去加載的文件,其實(shí)不然,在創(chuàng)建時(shí)由父類ExecutableArchiveLauncher的構(gòu)造方法去加載的文件。
加載為歸檔文件對(duì)象:
this.archive=createArchive();
具體的加載方法:判斷路徑是否是一個(gè)文件夾,是則返回ExplodedArchive對(duì)象,否則返回JarFileArchive進(jìn)入JarFileArchive類:通過這個(gè)new方法創(chuàng)建JarFile對(duì)象
publicclassJarFileArchiveimplementsArchive{
publicJarFileArchive(Filefile,URLurl)throwsIOException{
this(newJarFile(file));
this.url=url;
}
進(jìn)入到JarFile方法:通過RandomAccessDataFile讀取文件的內(nèi)容,并傳遞給本類中的方法進(jìn)行具體的解析。
publicclassJarFileextendsjava.util.jar.JarFile{
publicJarFile(Filefile)throwsIOException{
this(newRandomAccessDataFile(file));
}
進(jìn)入jarLauncher的launch方法:注冊(cè)URL協(xié)議的處理器,沒有指定時(shí),默認(rèn)指向org.springframework.boot.loader包路徑,獲取類路徑下的歸檔文件Archive并通過這些歸檔文件的URL,創(chuàng)建線程上下文類加載器,使用類加載器和用戶編寫的啟動(dòng)入口類,通過反射調(diào)用它的main方法。
protectedvoidlaunch(String[]args)throwsException{
JarFile.registerUrlProtocolHandler();
ClassLoaderclassLoader=createClassLoader(getClassPathArchives());
launch(args,getMainClass(),classLoader);
}
JarLauncher的getClassPathArchives是在ExecutableArchiveLauncher中實(shí)現(xiàn):獲取歸檔文件中滿足EntryFilterg過濾器的項(xiàng),isNestedArchive方法由具體的之類實(shí)現(xiàn)。獲取到當(dāng)前歸檔文件下的所有子歸檔文件之后的后置操作,是一個(gè)擴(kuò)展點(diǎn)。在JarLauncher中是一個(gè)空實(shí)現(xiàn)。
JarLauncher的具體實(shí)現(xiàn),這里通過判斷是否在BOOT-INF/lib/包下返回true也就是說只會(huì)把jar包下的BOOT-INF/lib/下的文件加載為Archive對(duì)象
protectedbooleanisNestedArchive(Archive.Entryentry){
if(entry.isDirectory()){
returnentry.getName().equals(BOOT_INF_CLASSES);
returnentry.getName().startsWith(BOOT_INF_LIB);
}
JarFileArchive的getNestedArchives方法:若匹配器匹配到則獲取內(nèi)嵌歸檔文件。
具體的獲取內(nèi)嵌歸檔文件邏輯:根據(jù)具體的Entry對(duì)象,創(chuàng)建JarFile對(duì)象并封裝成歸檔文件對(duì)象后返回。
protectedArchivegetNestedArchive(Entryentry)throwsIOException{
try{
JarFilejarFile=this.jarFile.getNestedJarFile(jarEntry);
returnnewJarFileArchive(jarFile);
}
獲取到參數(shù)entry對(duì)應(yīng)的RandomAccessData對(duì)象,這里根據(jù)springboot擴(kuò)展的url協(xié)議,在父路徑的基礎(chǔ)上添加!/來標(biāo)記子包。
privateJarFilecreateJarFileFromFileEntry(JarEntryentry)throwsIOException{
RandomAccessDataentryData=this.entries.getEntryData(entry.getName());
returnnewJarFile(this.rootFile,this.pathFromRoot+"!/"+entry.getName(),
entryData,JarFileType.NESTED_JAR);
}
到這基本上讀取jar內(nèi)部信息,加載為對(duì)應(yīng)歸檔文件對(duì)象的大概過程已經(jīng)講完了,接下來分析一下在獲取到了整個(gè)jar的歸檔文件對(duì)象后的處理。
通過歸檔文件對(duì)象列表,獲取對(duì)應(yīng)的url信息,并通過url信息創(chuàng)建LaunchedURLClassLoader
protectedClassLoadercreateClassLoader(ListArchivearchives){
ListURLurls=newArrayListURL(archives.size());
for(Archivearchive:archives){
urls.add(archive.getUrl());
returncreateClassLoader(urls.toArray(newURL[urls.size()]));
}
獲取到對(duì)應(yīng)的LaunchedUrlClassLoader類加載器之后,設(shè)置線程的上下文類加載器為該加載器。根據(jù)MANIFI.MF文件中的start-classs信息創(chuàng)建項(xiàng)目啟動(dòng)入口主類對(duì)象,并通過返回對(duì)象的run方法啟動(dòng)
protectedvoidlaunch(String[]args,StringmainClass,ClassLoaderclassLoader){
Thread.currentThread().setContextClassLoader(classLoader);
createMainMethodRunner(mainClass,args,classLoader).run();
}
進(jìn)入MainMethodRunner的run方法:先通過當(dāng)前線程獲取到main入口類,然后通過反射調(diào)用啟動(dòng)項(xiàng)目啟動(dòng)類的main方法
publicvoidrun()throwsException{
ClassmainClass=Thread.currentThread().getContextClassLoader()
.loadClass(this.mainClassName);
MethodmainMethod=mainClass.getDeclaredMethod("main",String[].class);
mainMethod.invoke(null,newObject[]{this.args});
}
最后來說一下這個(gè)LaunchedURLClassLoader,它繼承于URLClassLoader,并重寫了loadClass方法
LaunchedClassLoader的loadClass方法:調(diào)用父類loadClass方法,走正常委派流程,最終會(huì)被LaunchURLClassLoader加載。
@Override
protectedClassloadClass(Stringname,booleanresolve){
try{
try{
definePackageIfNecessary(name);
returnsuper.loadClass(name,resolve);
}
進(jìn)入U(xiǎn)RLClassLoader中根據(jù)springboot解析進(jìn)行解析。根據(jù)名稱將路徑轉(zhuǎn)化為以.class結(jié)尾的/分隔的格式。通過UrlClassPath對(duì)象根據(jù)路徑獲取資源類文件
newPrivilegedExceptionActionClass(){
publicClassrun()throwsClassNotFoundExcep
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 浙江大學(xué)《急危重癥護(hù)理學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 赤峰應(yīng)用技術(shù)職業(yè)學(xué)院《輕松學(xué)營(yíng)銷》2023-2024學(xué)年第二學(xué)期期末試卷
- 三門峽社會(huì)管理職業(yè)學(xué)院《電視欄目制作》2023-2024學(xué)年第二學(xué)期期末試卷
- 石家莊鐵道大學(xué)《藝術(shù)品市場(chǎng)營(yíng)銷》2023-2024學(xué)年第二學(xué)期期末試卷
- 溫室氣體與臭氧層相互作用-洞察及研究
- 物流公司組織管理制度
- 物流公司運(yùn)營(yíng)管理制度
- 物流車隊(duì)安全管理制度
- 物質(zhì)倉(cāng)庫(kù)安全管理制度
- 環(huán)境采樣部門管理制度
- 2024-2025學(xué)年高中中國(guó)航天日班會(huì) 課件 弘揚(yáng)航天精神 逐夢(mèng)星辰大海
- 不穩(wěn)定型心絞痛護(hù)理診斷及護(hù)理措施
- 藥品配送運(yùn)輸流程圖解
- 腹膜透析圍手術(shù)期的護(hù)理
- 虛擬實(shí)驗(yàn)在高中生物學(xué)實(shí)驗(yàn)教學(xué)中的應(yīng)用研究
- 糖尿病足護(hù)理疑難病例討論
- 頻繁停電培訓(xùn)課件
- 2025年度數(shù)據(jù)中心制冷設(shè)備采購(gòu)與安裝施工合同范本
- 2025年廣西宏桂資本運(yùn)營(yíng)集團(tuán)招聘筆試參考題庫(kù)含答案解析
- 英語中國(guó)文化
- 防水工程改造翻新合同
評(píng)論
0/150
提交評(píng)論