<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 的啟動(dòng)引導(dǎo)類(lèi)真的是XXApplication嗎?

          共 4496字,需瀏覽 9分鐘

           ·

          2020-12-10 02:58


          來(lái)源:https://my.oschina.net/floor/blog/4301613

          1. 引言

          SpringBoot項(xiàng)目中的啟動(dòng)類(lèi),一般都是XXApplication,例如StatsApplication,UnionApplication。每個(gè)項(xiàng)目的啟動(dòng)類(lèi)名稱(chēng)都不一樣。但是它的啟動(dòng)類(lèi)真的是XXApplication嗎?

          2. META-INF/Manifest.mf文件

          jar文件實(shí)際上是class文件的zip壓縮存檔。jar并不能表達(dá)應(yīng)用程序的便簽信息.

          META-INF/Manifest.mf文件提供存檔的便簽信息.

          Manifest.mf有 Main-Class,用來(lái)標(biāo)明jar文件的入口類(lèi)。

          解壓jar包,查看META-INF/Manifest.mf過(guò)程如下:

          重要信息如下

          Main-Class: org.springframework.boot.loader.JarLauncher
          Start-Class: com.shanyuan.StatsApplication

          也就是說(shuō):org.springframework.boot.loader.JarLauncher是SpringBoot的啟動(dòng)類(lèi)!

          下面瀏覽下JarLauncher

          3. 瀏覽JarLauncher

          3.1 找到JarLauncher

          進(jìn)入IDEA,Ctrl+N查找JarLauncher,竟然找不到!!

          進(jìn)入 https://search.maven.org/classic/#advancedsearch 查詢(xún)JarLauncher

          在查詢(xún)結(jié)果找到spring下的項(xiàng)目

          確定JarLauncher位于spring-boot-loader下。為了方便查看源碼,在pom中引入

          <dependency>
           <groupId>org.springframework.bootgroupId>
           <artifactId>spring-boot-loaderartifactId>
           <scope>providedscope>
          dependency>

          3.2.JarLauncher說(shuō)明

          JarLauncher作為引導(dǎo)類(lèi) ,當(dāng)調(diào)用java -jar 命令時(shí),將調(diào)用main方法,實(shí)際上調(diào)用的是 JarLauncher#launch方法,該方法繼承與org.springframework.boot.loader.Launcher

          簡(jiǎn)化層次關(guān)系為:

          JarLauncher#launch代碼如下

          protected void launch(String[] args) throws Exception {
             JarFile.registerUrlProtocolHandler();
             ClassLoader classLoader = createClassLoader(getClassPathArchives());
             launch(args, getMainClass(), classLoader);
          }

          聚句解析

          1,.JarFile.registerUrlProtocolHandler();

          Spring Boot生成的FAT jar,在被java -jar 引導(dǎo)時(shí),其內(nèi)部的jar文件無(wú)法被sun.net. www.protocol .jar.Handler處理。

          所以SpringBoot實(shí)現(xiàn)了,org.springframework.boot.loader.jar.Handler

          JarFile.registerUrlProtocolHandler(),就注冊(cè) org.springframework.boot.loader.jar.Handler

          2. ClassLoader classLoader = createClassLoader(getClassPathArchives());

          創(chuàng)建ClassLoader。

          getClassPathArchives 核心判斷是 isNestedArchive方法。

          isNestedArchive被JarLauncher覆寫(xiě)了。其實(shí)現(xiàn)如下:

          static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";

          static final String BOOT_INF_LIB = "BOOT-INF/lib/";
          @Override
          protected boolean isNestedArchive(Archive.Entry entry) {
             if (entry.isDirectory()) {
                return entry.getName().equals(BOOT_INF_CLASSES);
             }
             return entry.getName().startsWith(BOOT_INF_LIB);
          }

          也就是說(shuō),只要 滿(mǎn)足以BOOT-INF/classes/和BOOT-INF/lib/都是classLoader加載的范圍。

          解壓的jar,查看也與只對(duì)應(yīng)

          3. launch(args, getMainClass(), classLoader);

          protected void launch(String[] args, String mainClass, 
                          ClassLoader classLoader)

                throws Exception 
          {
             Thread.currentThread().setContextClassLoader(classLoader);
             createMainMethodRunner(mainClass, args, classLoader).run();
          }

          查看createMainMethodRunner的run方法,如下:

          public class MainMethodRunner {
              // 省略部分代碼
              public void run() throws Exception {
             Class mainClass = Thread.currentThread().getContextClassLoader()
                   .loadClass(this.mainClassName);
                 Method mainMethod = 
                     mainClass.getDeclaredMethod("main", String[].class);
                 mainMethod.invoke(nullnew Object[] { this.args });
              }
          }

          其中mainClass,來(lái)自/META-INF/MANIFEST.MF中的Start-Class屬性。

          即,JarLauncher是同進(jìn)程內(nèi),通過(guò)反射調(diào)用Start-Class對(duì)應(yīng)類(lèi),即XXXApplication的main方法。

          4.總結(jié)

          SpringBoot項(xiàng)目的實(shí)際啟動(dòng)類(lèi)是org.springframework.boot.loader.JarLauncher。

          在JarLauncher內(nèi)部通過(guò)反射調(diào)用XXApplication類(lèi)的main方法。

          具體實(shí)現(xiàn)位于 MainMethodRunner中。

          -END-

          我是武哥,最后給大家免費(fèi)分享我寫(xiě)的 10 萬(wàn)字 Spring Boot 學(xué)習(xí)筆記(帶完整目錄)以及對(duì)應(yīng)的源碼。這是我之前在 CSDN 開(kāi)的一門(mén)課,所以筆記非常詳細(xì)完整,我準(zhǔn)備將資料分享出來(lái)給大家免費(fèi)學(xué)習(xí),相信大家看完一定會(huì)有所收獲(下面有下載方式)。


          可以看出,我當(dāng)時(shí)備課非常詳細(xì),目錄非常完整,讀者可以手把手跟著筆記,結(jié)合源代碼來(lái)學(xué)習(xí)?,F(xiàn)在免費(fèi)分享出來(lái),有需要的讀者可以下載學(xué)習(xí),就在下面的公眾號(hào)Java禿頭哥里回復(fù):筆記,就行。



          如有文章對(duì)你有幫助,

          在看轉(zhuǎn)發(fā)是對(duì)我最大的支持



          關(guān)注Java禿頭哥

          只有禿頭才能更強(qiáng)


          點(diǎn)贊是最大的支持 

          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  日韩人妻精品在线 | 大鸡吧在线观看 | 日本一道码高清无码 | yy4080午夜一级 | 欧美日韩国产123区 |