<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我真不信,這年頭還有人能懂SpringBoot的ClassLoader加載機(jī)制

          共 3568字,需瀏覽 8分鐘

           ·

          2022-02-16 02:26


          SpringBoot的ClassLoader加載機(jī)制

          在Spring Boot的嵌入式Web容器原理一節(jié)中,我們已經(jīng)介紹了Spring Boot對Tomcat容器的加載過程,本節(jié)我們進(jìn)一步講解SpringBoot的ClassLoader加載機(jī)制。

          熟悉Tomcat工作原理的人應(yīng)該知道,Tomcat內(nèi)部實(shí)現(xiàn)了自定義的類加載器,打破了Java的雙親委派機(jī)制,下面我們先看看什么是雙親委派機(jī)制。


          雙親委派機(jī)制

          雙親委派機(jī)制是指Java的類加載器收到一個(gè)類加載請求時(shí),該類加載器首先會(huì)把請求委派給父類加載器。每個(gè)類加載器都是如此,只有當(dāng)父類加載器在自己的搜索范圍內(nèi)找不到指定類時(shí),子類加載器才會(huì)嘗試自己去加載。Java類加載機(jī)制如下圖所示。


          我們通常將類加載器分為下面的三種類型。

          ● 啟 動(dòng) 類 加 載 器 ( Bootstrap ClassLoader ) :加 載jre/lib/rt.jar。

          ● 擴(kuò) 展 類 加 載 器 ( Extension ClassLoader ) :加 載jre/lib/ext/*.jar。

          ● 應(yīng) 用 程 序 類 加 載 器 ( Application ClassLoader ) :加 載classpath上指定的類庫。

          如果使用JDK默認(rèn)的雙親委派模式,Tomcat的類加載器可以加載嗎?我們思考一下Tomcat作為一個(gè)Web容器的使用場景。

          在Web容器中,可能同時(shí)需要部署兩個(gè)以上的應(yīng)用程序。一個(gè)典型的場景是不同的應(yīng)用程序會(huì)依賴同一個(gè)第三方類庫的不同版本,不能要求同一個(gè)類庫在同一個(gè)服務(wù)器中只有一份,因此要保證每個(gè)應(yīng)用程序的類庫都是獨(dú)立的,保證相互隔離。

          Tomcat如果使用默認(rèn)類加載器,是無法加載兩個(gè)相同類庫的不同版本的。所以Tomcat團(tuán)隊(duì)設(shè)計(jì)了自己獨(dú)特的類加載機(jī)制,解決上面的應(yīng)用jar包沖突等問題,通過自定義的類加載機(jī)制可以完美地解決Tomcat容器中不同應(yīng)用的隔離問題。下面我們看看Tomcat的類加載機(jī)制圖和JDK默認(rèn)的加載機(jī)制圖的區(qū)別,如下圖所示。


          其中:

          ● Common ClassLoader:Tomcat最基本的類加載器,加載路徑中的Class可以被Tomcat容器本身及各個(gè)WebApp訪問。

          ● Catalina ClassLoader:Tomcat容器私有的類加載器,加載路徑中的Class對于WebApp不可見。

          ● Shared ClassLoader:各個(gè)WebApp共享的類加載器,加載路徑中的Class對所有WebApp可見,但是對于Tomcat容器不可見。

          ● WebApp ClassLoader:各個(gè)WebApp私有的類加載器,加載路徑中的Class只對當(dāng)前WebApp可見,各個(gè)項(xiàng)目就是通過各自的WebApp ClassLoader加載進(jìn)入Tomcat容器的。探索Spring Boot的ClassLoaderSpring Boot的內(nèi)置Tomcat是如何加載到我們的項(xiàng)目中的呢?我們還是從SpringApplication的run方法開始追溯Tomcat啟動(dòng)Web Server的過程,ApplicationContext執(zhí)行刷新操作并創(chuàng)建嵌入式容器,源碼如下:



          然后,進(jìn)入EmbeddedServletContainer的
          getEmbeddedServletContainer方法,它會(huì)初始化Tomcat實(shí)例并準(zhǔn)備Context。


          最后,跟進(jìn)prepareContext方法,我們就可以看到嵌入式Tomcat的類加載方式,源碼如下:



          可 見 , Spring Boot 以 啟 動(dòng) 線 程 的 Context ClassLoader 作 為Tomcat的WebApp ClassLoader的父類加載器,而Tomcat的WebApp類加載器使用
          TomcatEmbeddedWebAppClassLoader。所以整個(gè)項(xiàng)目的jar包的加載都是由Spring Boot的主線程Context ClassLoader完成的,于是Context ClassLoader就可以訪問我們的Web容器下的所有資源了。

          需要說明的是,Spring Boot使用了FatJar技術(shù)將所有依賴放在一個(gè)最終的jar包文件BOOT-INF/lib中,它可以把當(dāng)前項(xiàng)目的Class全部放在BOOT-INF/classes目錄中。你可以在Spring Boot的工程項(xiàng)目中看到,在pom.xml文件中引入了如下依賴:


          jar包目錄結(jié)構(gòu)如下:


          從這個(gè)目錄結(jié)構(gòu)中,你可以看到Tomcat的啟動(dòng)包(tomcat-embedcore-8.5.29.jar)就在Lib目錄下。而FatJar的啟動(dòng)Main函數(shù)就是JarLauncher,它負(fù)責(zé)創(chuàng)建LaunchedURLClassLoader來加載/lib下面的所有jar包。下面是Spring Boot應(yīng)用的Manifest文件內(nèi)容。


          這里的Main-Class是
          org.springframework.boot.loader.JarLauncher,它是這個(gè)jar包啟動(dòng)的Main函數(shù)。

          還有一個(gè)Start-Class:


          com.test.demo.SpringbootDemoApplication,它是應(yīng)用自己的Main函數(shù) 。Spring Boot 將 jar 包 中 的 Main-Class 進(jìn) 行 了 替 換 , 換 成 了JarLauncher,并增加了一個(gè)Start-Class參數(shù),這個(gè)參數(shù)對應(yīng)的類才是真正的業(yè)務(wù)Main函數(shù)入口。我們再看看這個(gè)JarLaucher具體干了什么,源碼如下:


          launch方法分為三步:(1)注冊URL協(xié)議并清除應(yīng)用緩存。

          (2)設(shè)置類加載路徑。

          (3)執(zhí)行main方法。

          這里面,Spring Boot自定義的ClassLoader能夠識別FatJar中的資源,包括:在指定目錄下的項(xiàng)目編譯Class、在指定目錄下的項(xiàng)目依賴jar包。Spring Boot支持多個(gè)!/分隔符,通過自行實(shí)現(xiàn)的ZipFile解析器實(shí)現(xiàn)了對URL插入的定制化Handler,將獲取的URL數(shù)據(jù)作為參數(shù)傳遞給自定義的URLClassLoader,最終實(shí)現(xiàn)資源的獲取和解析。

          綜上,在傳統(tǒng)的以Tomcat容器部署War包項(xiàng)目中,我們的Web項(xiàng)目其實(shí)是一個(gè)被加載對象。Tomcat容器作為主線程的父類加載器來加載不同的應(yīng)用,Tomcat獨(dú)特的WebApp ClassLoader各自加載不同目錄下的War包應(yīng)用,應(yīng)用之間使用ClassLoader實(shí)現(xiàn)了很好的隔離。

          Spring Boot主要通過實(shí)例化SpringApplication來啟動(dòng)應(yīng)用,內(nèi)置的Tomcat容器實(shí)現(xiàn)相關(guān)Web環(huán)境及初始化資源準(zhǔn)備,并將Tomcat內(nèi)嵌的WebApp ClassLoader作為子ClassLoader掛載到Spring Boot的主線程 Context ClassLoader 。同 時(shí) , Spring Boot 中 的 @Controller 、@RequestMapping 等 Web 服 務(wù) 資 源 通 過 自 動(dòng) 裝 配 機(jī) 制 , 在SpringApplication啟動(dòng)過程中通過掃描將資源對象加載到Spring IoC容器中。最后Spring Boot使用FatJar自定義的jar包壓縮和加載機(jī)制,規(guī)范了Spring Boot項(xiàng)目的包及目錄結(jié)構(gòu)。

          小結(jié)

          目前,基于腳手架(基底)模式進(jìn)行軟件構(gòu)建已經(jīng)成為微服務(wù)架構(gòu)落地的主流開發(fā)方式,可以顯著提升開發(fā)人員的工作效率。SpringBoot本身基于Spring框架,繼承了Spring強(qiáng)大的技術(shù)特性。本章我們對Spring Boot框架的核心模塊和機(jī)制進(jìn)行了剖析,詳細(xì)講解了SpringBoot的自動(dòng)化配置原理、Starter機(jī)制和自定義Starter的工作原理,固化了“約定優(yōu)于配置”和“開箱即用”等簡潔的開發(fā)理念和高效開發(fā)方式。同時(shí),本章也是后續(xù)Spring Cloud微服務(wù)治理的基礎(chǔ),在開始技術(shù)進(jìn)階之前,務(wù)必掌握Spring Boot基礎(chǔ)原理,這樣才能做到事半功倍。

          本文給大家講解的內(nèi)容是Spring Boot的ClassLoader加載機(jī)制

          1. 下篇文章給大家詳細(xì)講解服務(wù)注冊中心,歡迎大家來學(xué)習(xí)

          2. 覺得文章不錯(cuò)的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;

          3. 感謝大家的支持!


          本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。

          瀏覽 54
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线三级在线观看网站 | 久久字幕 | 美臀av| 免费的A片| 国产成人视频一区二区 |