目录
- Pre
- 引导
- 新建工程 打包 启动
- java -jar 干啥的
- 打包插件
- spring-boot-maven-plugin简介
- 包结构
- Archive的概念
- JarFile
- JarLauncher工作流程
- 小结
本篇文章将为大家讲述关于 SpringBoot 项目工程完成后,是如何通过 java-jar 命令来启动的,以及介绍 java-jar 命令的详细内容。希望本篇文章能够帮助到大家的学习!
Pre
大家开发的基于Spring Boot 的应用 ,jar形式, 发布的时候,绝大部分都是使用java -jar 启动。 得益于Spring Boot 的封装 , 再也不用操心搭建tomcat等相关web容器le , 一切变得非常美好, 那SpringBoot是怎么做到的呢?
引导
新建工程 打包 启动
我们新创建一个Spring Boot的工程
先打包一下
执行以上命令之后,便生成了打包结果对应的两个文件。
包结构
下面针对文件的内容和结构进行一探究竟。
spring-0.0.1-SNAPSHOT.jar ├── META-INF │ └── maven(主要是pom文件) │ └── MANIFEST.MF ├── BOOT-INF │ ├── classes │ │ └── 应用程序类 │ └── lib │ └── 第三方依赖jar └── org └── springframework └── boot └── loader └── springboot启动程序
META-INF内容
Manifest-Version: 1.0 Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Implementation-Title: spring Implementation-Version: 0.0.1-SNAPSHOT Spring-Boot-Layers-Index: BOOT-INF/layers.idx Start-Class: com.artisan.spring.Application Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Build-Jdk-Spec: 1.8 Spring-Boot-Version: 2.4.1 Created-By: Maven Jar Plugin 3.2.0 Main-Class: org.springframework.boot.loader.JarLauncher
Main-Class:org.springframework.boot.loader.JarLauncher ,这个是jar启动的Main函数Start-Class: com.artisan.spring.Application,这个是我们应用自己的Main函数
Archive的概念
在继续了解底层概念和原理之前,我们先来了解一下Archive的概念:
- archive即归档文件,这个概念在linux下比较常见
- 通常就是一个tar/zip格式的压缩包
- jar是zip格式
SpringBoot抽象了Archive的概念,一个Archive可以是jar(JarFileArchive),可以是一个文件目录(ExplodedArchive),可以抽象为统一访问资源的逻辑层
关于Spring Boot中Archive的源码如下:
public interface Archive extends Iterable<Archive.Entry> { // 获取该归档的url URL getUrl() throws MalformedURLException; // 获取jar!/META-INF/MANIFEST.MF或[ArchiveDir]/META-INF/MANIFEST.MF Manifest getManifest() throws IOException; // 获取jar!/BOOT-INF/lib/*.jar或[ArchiveDir]/BOOT-INF/lib/*.jar List<Archive> getNestedArchives(EntryFilter filter) throws IOException; }
SpringBoot定义了一个接口用于描述资源,也就是org.springframework.boot.loader.archive.Archive。
其主入口新建了JarLauncher并调用父类Launcher中的launch方法启动程序。在创建JarLauncher时,父类ExecutableArchiveLauncher找到自己所在的jar,并创建archive。
JarLauncher继承于org.springframework.boot.loader.ExecutableArchiveLauncher。该类的无参构造方法最主要的功能就是构建了当前main方法所在的FatJar的JarFileArchive对象。
下面来看launch方法。该方法主要是做了2个事情:
(1)以FatJar为file作为入参,构造JarFileArchive对象。获取其中所有的资源目标,取得其Url,将这些URL作为参数,构建了一个URLClassLoader。
(2)以第一步构建的ClassLoader加载MANIFEST.MF文件中Start-Class指向的业务类,并且执行静态方法main。进而启动整个程序。
public abstract class ExecutableArchiveLauncher extends Launcher { private final Archive archive; public ExecutableArchiveLauncher() { try { // 找到自己所在的jar,并创建Archive this.archive = createArchive(); } catch (Exception ex) { throw new IllegalStateException(ex); } } } public abstract class Launcher { protected final Archive createArchive() throws Exception { ProtectionDomain protectionDomain = getClass().getProtectionDomain(); CodeSource codeSource = protectionDomain.getCodeSource(); URI location = (codeSource == null ? null : codeSource.getLocation().toURI()); String path = (location == null ? null : location.getSchemeSpecificPart()); if (path == null) { throw new IllegalStateException("Unable to determine code source archive"); } File root = new File(path); if (!root.exists()) { throw new IllegalStateException( "Unable to determine code source archive from " + root); } return (root.isDirectory() ? new ExplodedArchive(root) : new JarFileArchive(root)); } }
在Launcher的launch方法中,通过以上archive的getNestedArchives方法找到/BOOT-INF/lib下所有jar及/BOOT-INF/classes目录所对应的archive,通过这些archives的url生成LaunchedURLClassLoader
,并将其设置为线程上下文类加载器,启动应用。
至此,才执行我们应用程序主入口类的main方法,所有应用程序类文件均可通过/BOOT-INF/classes加载,所有依赖的第三方jar均可通过/BOOT-INF/lib加载。
小结
- JarLauncher通过加载BOOT-INF/classes目录及BOOT-INF/lib目录下jar文件,实现了fat jar的启动。
- SpringBoot通过扩展JarFile、JarURLConnection及URLStreamHandler,实现了jar in jar中资源的加载。
- SpringBoot通过扩展URLClassLoader–LauncherURLClassLoader,实现了jar in jar中class文件的加载。
- WarLauncher通过加载WEB-INF/classes目录及WEB-INF/lib和WEB-INF/lib-provided目录下的jar文件,实现了war文件的直接启动及web容器中的启动。
通过spring-boot-plugin 生成了MANIFEST.MF , main-class 指定运行java -jar的主程序把依赖的jar文件 打包在fat jar.
以上就是关于 java -jar命令的详细内容以及 SpringBoot 如何使用 java -jar命令来启动项目的具体过程。
原文地址:https://blog.csdn.net/qq_36908872/article/details/127118772