




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
springboot應(yīng)用啟動原理分析springboot應(yīng)用啟動原理分析/springboot應(yīng)用啟動原理分析springbootquickstart在springboot里,很吸引人的一個特性是可以直接把應(yīng)用打包成為一個jar/war,然后這個jar/war是可以直接啟動的,不需要另外配置一個WebServer。如果之前沒有使用過springboot可以通過下面的demo來感受下。
下面以這個工程為例,演示如何啟動Springboot項目:gitclone:hengyunabc/spring—boot—demo。gitmvnspring-boot-demojava—jartarget/demo—0。0.1—SNAPSHOT.jar123如果使用的IDE是springsts或者idea,可以通過向?qū)韯?chuàng)建springboot項目。也可以參考官方教程:
HYPERLINK”"\l”getting—started-first-application”\t”_blank"\l”getting—started—first—application"""\t"_blank”原始的Jar是這樣子的:jar:0.0。1-SNAPSHOT。jar!/1jar包里的資源的URL:jar:0。0。1—SNAPSHOT.jar!/com/example/SpringBootDemoApplication.class1可以看到對于Jar里的資源,定義以’!/'來分隔.原始的Jar只支持一個’!/'。Springboot擴展了這個協(xié)議,讓它支持多個’!/’,就可以表示jarinjar,jarindirectory的資源了。比如下面的URL表示demo—0.0。1—SNAPSHOT.jar這個jar里lib目錄下面的spring-beans—4。2。3.RELEASE。jar里面的MANIFEST。MF:jar:0。0。1—SNAPSHOT.jar!/lib/spring—beans—4.2。3.RELEASE.jar!/META-INF/MANIFEST.MF1自定義URLStreamHandler,擴展Jar在構(gòu)造一個URL時,可以傳遞一個Handler,而JDK自帶有默認的Handler類,應(yīng)用可以自己注冊Handler來處理自定義的URL。publicURL(Stringprotocol,Stringhost,intport,Stringfile,URLStreamHandlerhandler)throwsMalformedURLException123456參考:
HYPERLINK”"\l”URL-java。lang。String—java.lang.String-int—java。lang.String—"\l”URL—java。lang.String—java.lang。String-int—java.lang。String—”\t”_blank"Springboot通過注冊了一個自定義的Handler類來處理多重jarinjar的邏輯。這個Handler內(nèi)部會用SoftReference來緩存所有打開過的JarFile。在處理像下面這樣的URL時,會循環(huán)處理'!/’分隔符,從最上層出發(fā),先構(gòu)造出demo-0。0.1-SNAPSHOT。jar這個JarFile,再構(gòu)造出spring-beans—4.2.3.RELEASE。jar這個JarFile,然后再構(gòu)造出指向MANIFEST.MF的JarURLConnection。jar:0.0.1—SNAPSHOT。jar!/lib/spring—beans-4。2.3。RELEASE.jar!/META-INF/MANIFEST。MF1//org。springframework。boot.loader。jar。HandlerpublicclassHandlerextendsURLStreamHandler{privatestaticfinalStringSEPARATOR="!/";privatestaticSoftReference<Map〈File,JarFile>〉root;@OverrideprotectedURLConnectionopenConnection(URLurl)throwsIOException{if(this.jarnull){returnnewJarURLConnection(url,this.jarFile);}try{returnnewJarURLConnection(url,getRootJar(url));}catch(Exceptionex){returnopenFallbackConnection(url,ex);}}publicJar(URLurl)throwsIOException{Stringspec=url。getFile();intseparatorIndex=spec.indexOf(SEPARATOR);if(separatorIndex==—1){thrownewMalformedURLException("JarURLdoesnotcontain!/separator”);}Stringname=spec。substring(0,separatorIndex);returngetRootJar);}12345678910111213141516171819202122232425ClassLoader如何讀取到Resource對于一個ClassLoader,它需要哪些能力?查找資源讀取資源對應(yīng)的API是:publicURLfindResource(Stringname)publicInputStreamgetResourceAsStream(Stringname)12上面提到,Springboot構(gòu)造LaunchedURLClassLoader時,傳遞了一個URL[]數(shù)組。數(shù)組里是lib目錄下面的jar的URL.對于一個URL,JDK或者ClassLoader如何知道怎么讀取到里面的內(nèi)容的?實際上流程是這樣子的:LaunchedURLClassLoader。loadClassURL。getContent()URL.openConnection()Handler.openConnection(URL)最終調(diào)用的是JarURLConnection的getInputStream()函數(shù)。//org.springframework。boot。loader.jar.JarURLConnection@OverridepublicInputStreamgetInputStream()throwsIOException{connect();if(this.jarEntryName。isEmpty()){thrownewIOException("noentrynamespecified”);}returnthis。jarEntryData。getInputStream();}123456789從一個URL,到最終讀取到URL里的內(nèi)容,整個過程是比較復(fù)雜的,總結(jié)下:springboot注冊了一個Handler來處理”jar:"這種協(xié)議的URLspringboot擴展了Jar,內(nèi)部處理jarinjar的情況在處理多重jarinjar的URL時,springboot會循環(huán)處理,并緩存已經(jīng)加載到的JarFile對于多重jarinjar,實際上是解壓到了臨時目錄來處理,可以參考Jar里的代碼在獲取URL的InputStream時,最終獲取到的是JarFile里的JarEntryData這里面的細節(jié)很多,只列出比較重要的一些點。然后,URLClassLoader是如何getResource的呢?URLClassLoader在構(gòu)造時,有URL[]數(shù)組參數(shù),它內(nèi)部會用這個數(shù)組來構(gòu)造一個URLClassPath:URLClassPathucp=newURLClassPath(urls);1在URLClassPath內(nèi)部會為這些URLS都構(gòu)造一個Loader,然后在getResource時,會從這些Loader里一個個去嘗試獲取.
如果獲取成功的話,就像下面那樣包裝為一個Resource.ResourcegetResource(finalStringname,booleancheck){finalURLurl;try{url=newURL(base,ParseUtil.encodePath(name,false));}catch(MalformedURLExceptione){thrownewIllegalArgumentException("name”);}finalURLConnectionuc;try{if(check){URLClassPath。check(url);}uc=url.openConnection();InputStreamin=uc.getInputStream();if(ucinstanceofJarURLConnection){/*Needtorememberthejaritcanbeclosed*inahurry.*/JarURLConnectionjuc=(JarURLConnection)uc;jarfile=JarLoader.checkJar(juc.getJarFile());}}catch(Exceptione){returnnull;}returnnewResource(){publicStringgetName(){returnname;}publicURLgetURL(){returnurl;}publicURLgetCodeSourceURL(){returnbase;}publicInputStreamgetInputStream()throwsIOException{returnuc.getInputStream();}publicintgetContentLength()throwsIOException{returnuc.getContentLength();}};}123456789101112131415161718192021222324252627282930313233343536從代碼里可以看到,實際上是調(diào)用了url.openConnection().這樣完整的鏈條就可以連接起來了。注意,URLClassPath這個類的代碼在JDK里沒有自帶,在這里看到
HYPERLINK””\l"506”\t"_blank”在IDE/開放目錄啟動Springboot應(yīng)用在上面只提到在一個fatjar里啟動Springboot應(yīng)用的過程,下面分析IDE里Springboot是如何啟動的.在IDE里,直接運行的Main函數(shù)是應(yīng)用自己的Main函數(shù):@SpringBootApplicationpublicclassSpringBootDemoApplication{publicstaticvoidmain(String[]args){SpringApplication。run(SpringBootDemoApplication.class,args);}}1234567其實在IDE里啟動Springboot應(yīng)用是最簡單的一種情況,因為依賴的Jar都讓IDE放到classpath里了,所以Springboot直接啟動就完事了.還有一種情況是在一個開放目錄下啟動Springboot啟動。所謂的開放目錄就是把fatjar解壓,然后直接啟動應(yīng)用。javaorg。springframework.boot。loader.JarLauncher1這時,Springboot會判斷當(dāng)前是否在一個目錄里,如果是的,則構(gòu)造一個ExplodedArchive(前面在jar里時是Jar),后面的啟動流程類似fatjar的.EmbeadTomcat的啟動流程判斷是否在web環(huán)境springboot在啟動時,先通過一個簡單的查找Servlet類的方式來判斷是不是在web環(huán)境:privatestaticfinalString[]WEB_ENVIRONMENT_CLASSES={"javax。servlet。Servlet",”org。springframework。web。context。ConfigurableWebApplicationContext”};privatebooleandeduceWebEnvironment(){for(StringclassName:WEB_ENVIRONMENT_CLASSES){if(!ClassUtils。isPresent(className,null)){returnfalse;}}returntrue;}1234567891011如果是的話,則會創(chuàng)建AnnotationConfigEmbeddedWebApplicationContext,否則Springcontext就是Ann
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度時尚消費品代理進口及市場布局合同
- 二零二五年度退休科研人員合作研發(fā)聘用合同
- 二零二五學(xué)年度學(xué)生校車安全乘車環(huán)境改善與優(yōu)化協(xié)議
- 股權(quán)代持協(xié)議書標準模板:2025年度股權(quán)置換與重組范本
- 二零二五年度校園安全責(zé)任與學(xué)生家長參與合同
- 二零二五年度購物中心日常保潔與應(yīng)急處理合同
- 三字經(jīng)中道理的故事解讀
- 旅游目的地營銷與品牌形象塑造研究
- 綠化零工勞務(wù)合同
- 產(chǎn)品供應(yīng)和分銷合同
- 單位下鄉(xiāng)租車方案
- 化工制圖第一章制圖的基本知識課件
- 《植物學(xué)》練習(xí)(二)根、莖、葉營養(yǎng)器官的聯(lián)系及變態(tài)
- 鼎和財險附加意外傷害醫(yī)療保險A款(互聯(lián)網(wǎng)專屬)條款
- 中暑-紅十字應(yīng)急救護培訓(xùn)課件
- 聯(lián)儲共備實施方案
- 光伏工程 危害辨識風(fēng)險評價表(光伏)
- 高壓電動機試驗報告模板
- 醫(yī)學(xué)課件-主動脈夾層ppt
- 氫氧化鈣化學(xué)品安全技術(shù)說明書
- 大眾Polo 2014款說明書
評論
0/150
提交評論