<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>

          Spring Boot 啟動(dòng)類真的是XXApplication?

          共 3249字,需瀏覽 7分鐘

           ·

          2020-10-01 05:03

          Java技術(shù)棧

          www.javastack.cn

          關(guān)注閱讀更多優(yōu)質(zhì)文章


          1. 引言

          SpringBoot項(xiàng)目中的啟動(dòng)類,一般都是XXApplication,例如StatsApplication,UnionApplication。

          每個(gè)項(xiàng)目的啟動(dòng)類名稱都不一樣。

          但是它的啟動(dòng)類真的是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文件的入口類。點(diǎn)擊這里獲取一份完整的 Spring Boot 學(xué)習(xí)筆記。

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

          重要信息如下

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

          也就是說(shuō):org.springframework.boot.loader.JarLauncher 才是 Spring Boot 的啟動(dòng)類!

          不熟悉 Spring Boot 的可以看下這個(gè)倉(cāng)庫(kù):https://github.com/javastacks/spring-boot-best-practice

          下面瀏覽下JarLauncher

          3. 瀏覽JarLauncher

          3.1 找到JarLauncher

          進(jìn)入IDEA,Ctrl+N查找JarLauncher,竟然找不到?。?/p>

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

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

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


          ????org.springframework.boot
          ????spring-boot-loader
          ????provided

          3.2.JarLauncher說(shuō)明

          JarLauncher作為引導(dǎo)類 ,當(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覆寫了。

          其實(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ō),只要 滿足以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(null,?new?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)類,即XXXApplication的main方法。

          4.總結(jié)

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

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

          具體實(shí)現(xiàn)位于 MainMethodRunner中。最后,關(guān)于?Spring Boot?系列教程可以關(guān)注公眾號(hào)Java技術(shù)棧獲取閱讀。

          作者:溫安適
          來(lái)源:https://my.oschina.net/floor/blog/4301613





          關(guān)注Java技術(shù)棧看更多干貨



          戳原文,獲取精選面試題!
          瀏覽 73
          點(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>
                  色婷婷综合视频 | 大香蕉色伊人 | 青青草免费在线公开视频 | 久久艹视频 | 国产一级a毛一级a看免费视频乱 |