zoukankan      html  css  js  c++  java
  • Spring Boot(1)启动流程源码分析

     
     
    本文用的spring boot版本:
    2.3.1.RELEASE

    1、spring boot可执行jar的内容

    1.1、怎么打包成可执行jar

    spring boot提供了一个spring-boot-maven-plugin的插件,用于将spring boot程序打包成可执行的jar包(fat jar),在pom.xml里加入这个插件

    <build>
         <plugins>
            <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    1.2、可执行jar包的目录结构和内容

    myspringboot-0.0.1-SNAPSHOT
       --BOOT-INF
             --classes  >里面是自己的springboot程序的class
             --lib  >pom.xml里的依赖jar
             --classpath.idx   >lib里jar包的清单
       --META-INF
             --maven  >maven的相关文件,pom.xml、pom.properties(gav)
             --MANIFEST.MF  >jar包的标准清单
       --org  >spring boot loader相关类
             --springframework
                 --boot
                      --loader
                          --JarLauncher.class
                          --WarLauncher.class
                          --...

    1.2.1、META-INF

    这个文件夹是fat jar包的标准要求。JAR原文Jar Archive File,是java的一种文档档式。MANIFEST.MF是生成fat jar时自动创建的。
    MAINIFEST.MF的内容如下:
     
    Manifest-Version: 1.0
    Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
    Implementation-Title: myspringboot
    Implementation-Version: 0.0.1-SNAPSHOT
    Start-Class: com.lionman.boot.MainApplication
    Spring-Boot-Classes: BOOT-INF/classes/
    Spring-Boot-Lib: BOOT-INF/lib/
    Build-Jdk-Spec: 1.8
    Spring-Boot-Version: 2.3.1.RELEASE
    Created-By: Maven Jar Plugin 3.2.0
    Implementation-Vendor: Pivotal Software, Inc.
    Main-Class: org.springframework.boot.loader.JarLauncher
    

      

    Main-Class是fat jar可执行主类名,即:org.springframework.boot.loader.JarLauncher,这个才是Spring Boot应用的入口。

    如果打成war包,Main-Class就是org.springframework.boot.loader.WarLauncher。

    1.2.2、spring boot lader相关类

    org:里面是spring boot loader相关类的字节码文件,即:spring boot程序启动需要的classes,这些classes所在的依赖包在我们写的spring boot程序里是并没有,因为只是启动使用。想看loader的源代码,需要手动加入到pom.xml
     
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-loader</artifactId>
    </dependency>

    这样就可以看到spring boot loader了

     打包时就是把这个jar里的内容拷贝到fat jar里。

    2、JarLauncher

    JarLauncher是spring boot loader进fat jar的入口,用Idea的JarApplication跟进调试。
     

    JarLauncher的main方法两步:new JarLauncher()、launch(args)

    2.2.1、new JarLauncher()

    JarLauncher是构造方法是一个空实现,所以会调用它的父类ExecutableArchiveLauncher的构造方法。
    附:JarLauncher、WarLauncher、ExecutableArchiveLauncher、Launcher关系图
     

     new JarLauncher()完成了构造Archive,这里即JarArchive。

     2.2.2、launch(args)

    launch(args)调用的是基类Launcher里的方法,源码如下:

    (1)getClassPathArchivesIterator()
    会获取应用的fat jar,返回类型是Iterator<Archive>
     
    (2)createClassLoader(getClassPathArchivesIterator())
    会创建一个新的类加载器LaunchedURLClassLoader(它的父类加载器是AppClassLoader),用于加载BOOT-INF下classese文件夹的所有class和lib文件夹里的所有jar。
     
    (3)getMainClass()
    获取MANIFEST.MF里Start-Class,即被@SpringBootAppliction注解修饰带有main方法的spring boot启动类。
     
    (4)launch(args, launchClass, classLoader)
     

     创建MainMethodRunner,反射调用spring boot启动类里的main方法。

    main()执行了,spring boot应用就正式启动了。

    3、spring boot为什么要自定义类加载器

    从上面的源码分析,可以看出,spring boot创建了自己的类加载器,叫LaunchedURLClassloader。
    spring boot想完成一个jar包完成整个程序的运行。jar in jar,无法进行加载。所以spring boot引入自定义类加载器去解决那些不符合jar规格的类加载问题。
     
    spring boot这种优雅的方式,将我们自己的类和第三方jar包全部分开放置,AppClassLoader加载符合规范的Spring Boot ClassLoader(LaunchedURLClassloader)后,整个后续的类加载操作都会由自定义类加载器去加载,完美得实现了jar包的嵌套,带来了太多的便利。
     

    4、附:JarLauncher流程图

  • 相关阅读:
    对于匿名对象,内部类这块的理解
    final等关键字和代码块
    构造方法
    接口与多态的总结
    关于折半法查找的一些总结以及ArrayList类的总结
    关于冒泡法的总结(主要是格式问题了)
    java读取properties文件的几种方式(转载)
    JAVA导出EXCEL表格(转载)
    map遍历的四种方法
    Java集合源码分析(四)HashMap
  • 原文地址:https://www.cnblogs.com/onezg/p/13192066.html
Copyright © 2011-2022 走看看