springboot應(yīng)用啟動原理分析_第1頁
springboot應(yīng)用啟動原理分析_第2頁
springboot應(yīng)用啟動原理分析_第3頁
springboot應(yīng)用啟動原理分析_第4頁
springboot應(yīng)用啟動原理分析_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論