为什么springboot的jar可以直接启动

打印 上一主题 下一主题

主题 966|帖子 966|积分 2898

一、讲述
1.SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。
2.Spring Boot应用打包之后,天生一个Fat jar(jar包中包罗jar),包罗了应用依靠的jar包和Spring Boot loader相干的
类。
3.java -jar会去找jar中的manifest文件,在那边面找到真正的启动类(Main-Class);
4.Fat jar的启动Main函数是JarLauncher,它负责创建一个LaunchedURLClassLoader来加载boot-lib下面的jar,并以一个新线程启动应用的启动类的Main函数(找到manifest中的Start-Class)。
二、原理
SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。pom文件配置如下
  1. <plugin>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-maven-plugin</artifactId>
  4.     <version>${spring-boot.version}</version>
  5. </plugin>
复制代码
插件spring-boot-maven-plugin,提供了7个maven goal


  • build-image: 将程序使用 buildpack 打包进容器镜像中。
  • build-info:天生项目的构建信息文件 build-info.properties
  • help:表现帮助信息。调用mvn spring-boot:help -Ddetail=true -Dgoal=以表现参数详细信息。
  • repackage:可天生可执行的jar包或war包。插件的核心goal。
  • run:运行 Spring Boot 应用
  • start:在集成测试阶段,控制生命周期
  • stop:在集成测试阶段,控制生命周期
2、通过mvn package命令,Maven首先会按照标准流程构建项目,随后spring-boot-maven-plugin会执行repackage目标,该目标会重新包装已天生的标准JAR文件,将其转换为包罗所有依靠项和适当的启动器信息的Fat JAR。这样天生的JAR可以直接通过java -jar命令启动。jar内部目录如下


  • META-INF/: 包罗MANIFEST.MF文件和其他元数据信息,其中Main-Class属性指向Spring Boot的启动类加载器。
  • BOOT-INF/classes/: 存放项目自身的类文件和资源文件。
  • BOOT-INF/lib/: 放置所有依靠的jar包,包括Spring Boot starter依靠以及其他第三方库。(如果项目中有静态资源文件,也会在BOOT-INF下有对应的static、templates等目录)
3、Spring Boot启动器与Loader机制与MANIFEST.MF文件
Spring Boot应用的jar包可以直接运行主要依靠于它的启动器以及Loader机制,而对于Loader机制主要利用MANIFEST.MF文件以及其内部类加载逻辑。
MANIFEST.MF是JAR文件内的一个标准元数据文件,它包罗了关于JAR包的基本信息和运行指令。在jvm规范单中java -jar指令中会规范一个main方法,而这个main方法就在MANIFEST.MF文件中的Main-Class属性,这个类通常是org.springframework.boot.loader.JarLauncher或其他由Spring Boot提供的启动器类。Start-Class属性是启动应用的main方法。JarLauncher会通过一个子线程启动Start-Class中的main方法

4、JarLauncher执行流程
JarLauncher 入口 main 方法
  1. public static void main(String[] args) throws Exception {
  2.     // launch 方法是调用父类 Launcher 的 launch 方法
  3.     new JarLauncher().launch(args);
  4. }
复制代码
这里是加载清单文件的中的配置
  1.    /**
  2.          * Launch the application. This method is the initial entry point that should be
  3.          * called by a subclass {@code public static void main(String[] args)} method.
  4.            启动一个应用,这个方法应该被初始的入口点,这个入口点应该是一个Launcher的子类的
  5.            public static void main(String[] args)这样的方法调用
  6.          * @param args the incoming arguments
  7.          * @throws Exception if the application fails to launch
  8.          */
  9.         protected void launch(String[] args) throws Exception {
  10.                 if (!isExploded()) {
  11.                   // 注册一些 URL的属性
  12.                         JarFile.registerUrlProtocolHandler();
  13.                 }
  14.                 // 创建类加载器(LaunchedURLClassLoader),加载得到集合要么是BOOT-INF/classes/,或者BOOT-INF/lib/的目录或者是他们下边的class文件或者jar依赖文件
  15.                 ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
  16.                 String jarMode = System.getProperty("jarmode");
  17.                 String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
  18.                 // 执行应用的main方法
  19.                 launch(args, launchClass, classLoader);
  20.         }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

欢乐狗

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表