java_jdk

SpringBoot可执行jar文件原理分析

2019-10-22  本文已影响0人  null_2a46

Spring官网对SpringBoot的介绍中有这么一句话 Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".。其大概意思是说SpringBoot可以让我们更容易的创建一个独立的生产级别的Spring应用,只需要运行它就可以了。Spring官网阐述的SpringBoot六大特征中的第一个就是Create stand-alone Spring applications

SpringBoot应用可执行JAR资源结构

有过SpringBoot使用经验的人都知道,SpringBoot应用可以打成一个jar包,执行java -jar命令即可运行。下面探究一下通过java -jar命令启动SpringBoot打包的jar文件设计的内部细节和原理。

通过maven打包后,在项目的target目录下可以找到两个jar文件:first-spring-boot-application-1.0.0-SNAPSHOT.jarfirst-spring-boot-application-1.0.0-SNAPSHOT.jar.original。通过文件名和这两个jar文件大小可以分析出first-spring-boot-application-1.0.0-SNAPSHOT.jar.original为Maven打包的原始jar文件,而first-spring-boot-application-1.0.0-SNAPSHOT.jar为引入了相关第三方依赖资源后的jar包。

解压这两个jar文件,分析其内部的文件结构

$ unzip first-spring-boot-application-1.0.0-SNAPSHOT.jar -d temp
$ tree temp/
temp/
├── BOOT-INF
│   ├── classes
│   │   └── thinking
│   │       └── in
│   │           └── spring
│   │               └── boot
│   │                   └── App.class
│   └── lib
│       ├── classmate-1.3.4.jar
│       ├── hibernate-validator-6.0.9.Final.jar
│       ├── .....
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│       └── thinking-in-spring-boot
│           └── first-spring-boot-application
│               ├── pom.properties
│               └── pom.xml
└── org
    └── springframework
        └── boot
            └── loader
                ├── ExecutableArchiveLauncher.class
                ├── JarLauncher.class
                ├── ......
                └── util
                    └── SystemPropertyUtils.class
19 directories, 90 files

$ unzip first-spring-boot-application-1.0.0-SNAPSHOT.jar.original -d original
$ tree original/
original/
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│       └── thinking-in-spring-boot
│           └── first-spring-boot-application
│               ├── pom.properties
│               └── pom.xml
└── thinking
    └── in
        └── spring
            └── boot
                └── App.class

8 directories, 4 files

发现first-spring-boot-application-1.0.0-SNAPSHOT.jar解压后的文件目录中:

比较两者解压后的文件资源组成,除了META-INF目录,其他资源均发生了变化,“repackage”后的jar,将应用class文件和application.properties文件从根目录放置到了BOOT-INF/classes,所依赖的jar均存放到了BOOT-INF/lib目录。
标准的Java EE Web应用中,class文件存放在WEB-INF/classes目录,依赖的jar包存放在WEB-INF/lib目录。所以可以看出springboot打包出来的jar文件中BOOT-INF/classBOOT-INF/lib是仿照Java web应用的目录格式的。那么java -jar命令为何能执行jar文件呢。

FAT JAR和WAR执行模块——spring-boot-loader

Java官方文档规定java -jar命令引导的具体启动类必须配置在MANIFEST.MF资源的Main-Class属性中。同时JAR文件规范MANIFEST.MF资源必须存放在/META-INF/目录下。

$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Implementation-Title: 《Spring Boot 编程思想》第一个 Spring B
 oot 应用
Implementation-Version: 1.0.0-SNAPSHOT
Built-By: fengyajun
Implementation-Vendor-Id: thinking-in-spring-boot
Spring-Boot-Version: 2.0.2.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: thinking.in.spring.boot.App
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.6.0
Build-Jdk: 1.8.0_144
Implementation-URL: http://maven.apache.org

发现Main-Class属性指向的classorg.springframework.boot.loader.JarLauncher,存放在org/springframework/boot/loader/目录下,而项目的引导类则定义在Start-Class属性中。其中org.springframework.boot.loader.JarLauncher类是org.springframe.boot:spring-boot-loader:2.0.2.RELEASE包中的。因此运行 Java org.springframework.boot.loader.JarLauncher即可启动该应用。

$ java org.springframework.boot.loader.JarLauncher
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.2.RELEASE)
.......
INFO 72527 --- [main] thinking.in.spring.boot.App : Started App in 5.406 seconds (JVM running for 6.148)
上一篇 下一篇

猜你喜欢

热点阅读