国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Spring-Boot啟動(dòng)之前做了哪些事?

susheng / 708人閱讀

摘要:也就是說(shuō),可以執(zhí)行成功,是因?yàn)橹懒说穆窂剑f(shuō)明在啟動(dòng)調(diào)用之前,指定了的位置。判斷當(dāng)前的介質(zhì),是啟動(dòng),還是啟動(dòng)。

Spring-Boot啟動(dòng)之前做了哪些事? Spring Boot Jar文件探究

初始化一個(gè)Spring 應(yīng)用,添加如下依賴(lài)



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.6.RELEASE
         
    
    com.fxipp.spring
    first-app-by-gui
    0.0.1-SNAPSHOT
    first-app-by-gui
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

執(zhí)行mvn package命令打包,查看jar包的目錄結(jié)構(gòu)

.
├── BOOT-INF
│?? ├── classes
│?? │?? ├── application.properties
│?? │?? └── com
│?? │??     └── fxipp
│?? │??         └── spring
│?? │??             └── FirstAppByGuiApplication.class
│?? └── lib
│??     ├── classmate-1.4.0.jar
│??     ├── hibernate-validator-6.0.17.Final.jar
│??     ├── jackson-annotations-2.9.0.jar
│??     ├── jackson-core-2.9.9.jar
│??     ......
├── META-INF
│?? ├── MANIFEST.MF
│?? └── maven
│??     └── com.fxipp.spring
│??         └── first-app-by-gui
│??             ├── pom.properties
│??             └── pom.xml
└── org
    └── springframework
        └── boot
            └── loader
                ├── ExecutableArchiveLauncher.class
                ├── JarLauncher.class
                ├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
                ├── LaunchedURLClassLoader.class
                ├── ......
                ├── archive
                │?? ├── Archive$Entry.class
                │?? ├── Archive$EntryFilter.class
                │?? ├── Archive.class
                │?? ├── ......
                ├── data
                │?? ├── RandomAccessData.class
                │?? ├── RandomAccessDataFile$1.class
                │?? ├──......
                ├── jar
                │?? ├── AsciiBytes.class
                │?? ├── Bytes.class
                │?? ├── ......
                └── util
                    └── SystemPropertyUtils.class
18 directories, 91 files

文件結(jié)構(gòu)比較復(fù)雜,解釋一下

BOOT-INF/classes: 存放應(yīng)用編譯后的class文件;

BOOT-INF/lib:class path目錄, 存放應(yīng)用依賴(lài)的jar包;

META-INF: 存放應(yīng)用的元信息,如MANIFEST.MF文件;

org:存放Spring Boot自身的class文件;

Jar文件的執(zhí)行器: Spring Boot Loader

我們先從MANIFEST.MF文件查看

Manifest-Version: 1.0
Implementation-Title: first-app-by-gui
Implementation-Version: 0.0.1-SNAPSHOT
Start-Class: com.fxipp.spring.FirstAppByGuiApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.6.RELEASE
Created-By: Maven Archiver 3.4.0
Main-Class: org.springframework.boot.loader.JarLauncher

里面記錄了應(yīng)用的元信息,Spring的版本,應(yīng)用的版本,Maven的版本,Main-Class等信息。不難發(fā)現(xiàn),MainClass指向的是org.springframework.boot.loader.JarLauncher(以下簡(jiǎn)稱(chēng)JarLauncher),而不是我們自己編寫(xiě)的com.fxipp.spring.FirstAppByGuiApplication

JarLauncher從名字看出是一個(gè)jar的執(zhí)行器,他的class文件位于org.springframework.boot.loader目錄下,可見(jiàn)它是Spring自身的class文件。

JarLauncher的GAV org.springframework.boot:spring-boot-loader:2.1.6.RELEASE

通常情況下,他會(huì)在spring-boot-starter-parent引入到應(yīng)用中,既然main-class指向到是JarLauncher,那我們也可以直接執(zhí)行java org.springframework.boot.loader.JarLauncher,也可以啟動(dòng)Spring項(xiàng)目的。

java org.springframework.boot.loader.JarLauncher

  .   ____          _            __ _ _
 / / ___"_ __ _ _(_)_ __  __ _    
( ( )\___ | "_ | "_| | "_ / _` |    
 /  ___)| |_)| | | | | || (_| |  ) ) ) )
  "  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

2019-06-19 20:30:52.202  INFO 3094 --- [           main] c.fxipp.spring.FirstAppByGuiApplication  : Starting FirstAppByGuiApplication on fangxideMacBook-Pro.local with PID 3094 (/Users/fangxi/Java/workspace/default/spring-boot/first-app-by-gui/target/temp/BOOT-INF/classes started by fangxi in /Users/fangxi/Java/workspace/default/spring-boot/first-app-by-gui/target/temp)

既然可以執(zhí)行,那就說(shuō)明了,JarLauncher這個(gè)類(lèi)才是Spring項(xiàng)目真正的入口。如果我們執(zhí)行自己寫(xiě)的com.fxipp.spring.FirstAppByGuiApplication會(huì)怎么樣?

?  classes java com.fxipp.spring.FirstAppByGuiApplication
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
    at com.fxipp.spring.FirstAppByGuiApplication.main(FirstAppByGuiApplication.java:10)
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

啟動(dòng)報(bào)錯(cuò),原因是找不到org.springframework.boot.SpringApplication這個(gè)類(lèi),說(shuō)白了就是沒(méi)有指定Class Path,Spring Boot應(yīng)用的Class Path目錄是BOOT-INF/lib

也就是說(shuō),JarLauncher可以執(zhí)行成功,是因?yàn)镾pring Boot知道了Class Path的路徑,說(shuō)明JarLauncher在啟動(dòng)調(diào)用com.fxipp.spring.FirstAppByGuiApplication之前,指定了Class Path的位置。

JarLauncher的代碼如下

public class JarLauncher extends ExecutableArchiveLauncher {

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

   static final String BOOT_INF_LIB = "BOOT-INF/lib/";

   public JarLauncher() {
   }

   protected JarLauncher(Archive archive) {
      super(archive);
   }

   @Override
   protected boolean isNestedArchive(Archive.Entry entry) {
      if (entry.isDirectory()) {
         return entry.getName().equals(BOOT_INF_CLASSES);
      }
      return entry.getName().startsWith(BOOT_INF_LIB);
   }

   public static void main(String[] args) throws Exception {
      new JarLauncher().launch(args);
   }

}

Archive.Entry:這個(gè)類(lèi)對(duì)對(duì)象,代編jar包中的資源文件。

isNestedArchive方法判斷entry對(duì)象是不是位于jar包內(nèi),如果在jar內(nèi)部,返回true。如果不在jar包里面,也就是我們解壓了jar包,返回false。

重點(diǎn)看launch(String[])方法

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

這個(gè)方法一共3步

擴(kuò)展JAR協(xié)議

JDK默認(rèn)支持file、http、jar等協(xié)議,所以JDK內(nèi)部有默認(rèn)的實(shí)現(xiàn),位于sun.net.www.protocol包下。

JarFile.registerUrlProtocolHandler();這個(gè)方法將org.springframework.boot.loader包下對(duì)應(yīng)的JAR協(xié)議實(shí)現(xiàn),覆蓋原有的JAR實(shí)現(xiàn)。

因?yàn)樵械腏AR實(shí)現(xiàn),ClassPath是我們自己配置環(huán)境變量的時(shí)候制定的,不是BOOT-INF/lib

創(chuàng)建一個(gè)classloader,用于加載JarLauncher類(lèi),因?yàn)閖ar包可能會(huì)被解壓,解壓前和解壓后的的ClassLoader是不同的。

調(diào)用launch方法,將參數(shù)傳遞。

args是我們自己指定的參數(shù)。

getMainClass()是獲取MANIFEST.MF文件里面Statr-Class屬性,也就是獲取我們自定義主類(lèi)的Class 文件地址。

傳遞推出的類(lèi)加載器

launch方法

protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
   Thread.currentThread().setContextClassLoader(classLoader);
   createMainMethodRunner(mainClass, args, classLoader).run();
}

protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
   return new MainMethodRunner(mainClass, args);
}


public class MainMethodRunner {

   private final String mainClassName;

   private final String[] args;

   public MainMethodRunner(String mainClass, String[] args) {
      this.mainClassName = mainClass;
      this.args = (args != null) ? args.clone() : null;
   }

   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 });
   }

}

launch方法分析:

將ClassLoader放入當(dāng)前線程里面的ClassLoader里面

創(chuàng)建MainMethodRunner對(duì)象,調(diào)用里面的run()方法。

run()方法先獲取到之前設(shè)定的ClassLoader。

利用ClassLoader加載Start-Class之類(lèi)的類(lèi),也就是我們自己的主類(lèi)。

獲取主類(lèi)里面的main方法,通過(guò)反射執(zhí)行。

總結(jié)

通過(guò)分析,我們可以看出,Spring Boot Loader在調(diào)用我們自己的主類(lèi)之前,主要做了三件事

擴(kuò)展JDK默認(rèn)的支持JAR對(duì)應(yīng)的協(xié)議,因?yàn)镾pring Boot啟動(dòng)不僅僅需要JDK半身的JAR文件,還需要BOOT-INF/lib這個(gè)目錄下的文件。默認(rèn)實(shí)現(xiàn)無(wú)法將BOOT-INF/lib這個(gè)目錄當(dāng)作ClassPath,故需要替換實(shí)現(xiàn)。

判斷當(dāng)前的介質(zhì),是java -jar啟動(dòng),還是java org.springframework.boot.loader.JarLauncher啟動(dòng)。以便獲取對(duì)應(yīng)的ClassLoader。

獲取MANIFEST.MF文件中的Start-Class屬性,也就是我們自定義的主類(lèi)。通過(guò)第二步獲取的ClassLoader加載獲取到Class文件,通過(guò)反射調(diào)用main方法,啟動(dòng)應(yīng)用。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/75442.html

相關(guān)文章

  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(八)--制作Starter

    摘要:服務(wù)器相關(guān)配置啟動(dòng)類(lèi)資源目錄目錄靜態(tài)文件目錄端口號(hào)目錄目錄實(shí)現(xiàn)內(nèi)嵌服務(wù)器在上一章文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架七實(shí)現(xiàn)已經(jīng)在文件中引入了依賴(lài),所以這里就不用引用了。 spring-boot的Starter 一個(gè)項(xiàng)目總是要有一個(gè)啟動(dòng)的地方,當(dāng)項(xiàng)目部署在tomcat中的時(shí)候,經(jīng)常就會(huì)用tomcat的startup.sh(startup.bat)的啟動(dòng)腳本來(lái)啟動(dòng)web項(xiàng)目 而在spring-b...

    AprilJ 評(píng)論0 收藏0
  • Spring-Boot學(xué)習(xí)筆記

    摘要:學(xué)習(xí)筆記使用很容易創(chuàng)建一個(gè)獨(dú)立運(yùn)行運(yùn)行內(nèi)嵌容器準(zhǔn)生產(chǎn)級(jí)別的基于框架的項(xiàng)目,使用你可以不用或者只需要很少的配置。異常消息如果這個(gè)錯(cuò)誤是由異常引起的。錯(cuò)誤發(fā)生時(shí)請(qǐng)求的路徑。 Spring-Boot 1.5 學(xué)習(xí)筆記 使用Spring Boot很容易創(chuàng)建一個(gè)獨(dú)立運(yùn)行(運(yùn)行jar,內(nèi)嵌Servlet容器)、準(zhǔn)生產(chǎn)級(jí)別的基于Spring框架的項(xiàng)目,使用Spring Boot你可以不用或者只需要很...

    curlyCheng 評(píng)論0 收藏0
  • 三.spring-boot:簡(jiǎn)述springboot啟動(dòng)流程

    摘要:如下頁(yè)面模版的配置啟動(dòng)簡(jiǎn)單流程當(dāng)我們運(yùn)行的方法時(shí)調(diào)用靜態(tài)方法首先是實(shí)例化初始化的時(shí)候主要做主要做三件事根據(jù)下是否存在判斷是否要啟動(dòng)一個(gè)。將配置環(huán)境加入到監(jiān)聽(tīng)器對(duì)象中。方法將等重要組件與上下文對(duì)象關(guān)聯(lián)。自此的簡(jiǎn)單流程到此結(jié)束。 正文 說(shuō)springboot的啟動(dòng)流程當(dāng)然少不了springboot啟動(dòng)入口類(lèi) @SpringBootApplication public class Sprin...

    masturbator 評(píng)論0 收藏0
  • 使用Docker部署Spring-Boot+Vue博客系統(tǒng)

    摘要:先來(lái)看一下容器的文件中間一些操作省略這里用了多階段構(gòu)建容器,如果直接通過(guò)設(shè)置環(huán)境變量只會(huì)在后面一個(gè)階段生效,但是是在第一個(gè)階段執(zhí)行的,所以環(huán)境變量不能應(yīng)用到當(dāng)中。 在今年年初的時(shí)候,完成了自己的個(gè)Fame博客系統(tǒng)的實(shí)現(xiàn),當(dāng)時(shí)也做了一篇博文Spring-boot+Vue = Fame 寫(xiě)blog的一次小結(jié)作為記錄和介紹。從完成實(shí)現(xiàn)到現(xiàn)在,也斷斷續(xù)續(xù)的根據(jù)實(shí)際的使用情況進(jìn)行更新。 只不過(guò)每...

    Eirunye 評(píng)論0 收藏0
  • Spring Boot啟動(dòng)過(guò)程及回調(diào)接口匯總

    摘要:創(chuàng)建及準(zhǔn)備創(chuàng)建。目前已知關(guān)心這個(gè)事件的有要注意的是在這個(gè)階段,里只有,是的加載工作的起點(diǎn)。原因是注入這些回調(diào)接口本身沒(méi)有什么意義。在其構(gòu)造函數(shù)內(nèi)部間接的給注冊(cè)了幾個(gè)與相關(guān)注解的處理器。 相關(guān)代碼在: https://github.com/chanjarster/spring-boot-all-callbacks 注:本文基于spring-boot 1.4.1.RELEASE, spri...

    Taonce 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<