日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring Boot如何通過java -jar啟動

瀏覽:159日期:2022-08-12 08:28:01
目錄Pre引導新建工程 打包 啟動java -jar 干啥的打包插件spring-boot-maven-plugin簡介包結構Archive的概念JarFileJarLauncher工作流程小結Pre

大家開發的基于Spring Boot 的應用 ,jar形式, 發布的時候,絕大部分都是使用java -jar 啟動。 得益于Spring Boot 的封裝 , 再也不用操心搭建tomcat等相關web容器le , 一切變得非常美好, 那SpringBoot是怎么做到的呢?

Spring Boot如何通過java -jar啟動

引導新建工程 打包 啟動

我們新創建一個Spring Boot的工程

Spring Boot如何通過java -jar啟動

其中打包的配置為

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

先打包一下

Spring Boot如何通過java -jar啟動

查看target目錄

Spring Boot如何通過java -jar啟動

然后啟動

Spring Boot如何通過java -jar啟動

Spring Boot如何通過java -jar啟動

java -jar 干啥的

我們先看看 java -jar 干了啥 ?

在oracle官網找到了該命令的描述:

If the -jar option is specified, its argument is the name of the JAR file containing class and resource files for the application. The startup class must be indicated by the Main-Class manifest header in its source code.

使用-jar參數時,后面的參數是的jar 【spring-0.0.1-SNAPSHOT.jar】,該jar文件中包含的是class和資源文件; 在manifest文件中有Main-Class的定義;Main-Class的源碼中指定了整個應用的啟動類;

簡單來說: java -jar會去找jar中的manifest文件,去找到Main-Class對應的真正的啟動類;

那看看去吧

Spring Boot如何通過java -jar啟動

咦 ,這個Main-Class 是Spring Boot 的。

我們還看到有個Start Class

Spring Boot如何通過java -jar啟動

官方文檔中,只提到過Main-Class ,并沒有提到Start-Class;Start-Class的值是com.artisan.spring.Application,這是我們的java代碼中的唯一類,包含main方法, 是能夠真正的應用啟動類

Spring Boot如何通過java -jar啟動

所以問題就來了:理論上看,執行java -jar命令時JarLauncher類會被執行,但實際上是com.artisan.spring.Application被執行了,這其中發生了什么呢?why?

Spring Boot如何通過java -jar啟動

打包插件

事實上,Java沒有提供任何標準的方式來加載嵌套的jar文件 (jar中包含jar ,即Spring Boot 中的fat jar)

Spring Boot 默認的打包插件如下:

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

執行maven clean package之后,會生成兩個文件,剛才我們也看到了

Spring Boot如何通過java -jar啟動

spring-boot-maven-plugin簡介

spring-boot-maven-plugin項目存在于spring-boot-tools目錄中。

spring-boot-maven-plugin默認有5個goals:repackage、run、start、stop、build-info。在打包的時候默認使用的是repackage。

spring-boot-maven-plugin的repackage能夠將mvn package生成的軟件包,再次打包為可執行的軟件包,并將mvn package生成的軟件包重命名為.original*

spring-boot-maven-plugin的repackage在代碼層面調用了RepackageMojo的execute方法,而在該方法中又調用了repackage方法。

private void repackage() throws MojoExecutionException { // maven生成的jar,最終的命名將加上.original后綴 Artifact source = getSourceArtifact(); // 最終為可執行jar,即fat jar File target = getTargetFile(); // 獲取重新打包器,將maven生成的jar重新打包成可執行jar Repackager repackager = getRepackager(source.getFile()); // 查找并過濾項目運行時依賴的jar Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(), getFilters(getAdditionalFilters())); // 將artifacts轉換成libraries Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack, getLog()); try { // 獲得Spring Boot啟動腳本 LaunchScript launchScript = getLaunchScript(); // 執行重新打包,生成fat jar repackager.repackage(target, libraries, launchScript); }catch (IOException ex) { throw new MojoExecutionException(ex.getMessage(), ex); } // 將maven生成的jar更新成.original文件 updateArtifact(source, target, repackager.getBackupFile());}

執行以上命令之后,便生成了打包結果對應的兩個文件。

Spring Boot如何通過java -jar啟動

包結構

下面針對文件的內容和結構進行一探究竟。

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.0Spring-Boot-Classpath-Index: BOOT-INF/classpath.idxImplementation-Title: springImplementation-Version: 0.0.1-SNAPSHOTSpring-Boot-Layers-Index: BOOT-INF/layers.idxStart-Class: com.artisan.spring.ApplicationSpring-Boot-Classes: BOOT-INF/classes/Spring-Boot-Lib: BOOT-INF/lib/Build-Jdk-Spec: 1.8Spring-Boot-Version: 2.4.1Created-By: Maven Jar Plugin 3.2.0Main-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

Spring Boot如何通過java -jar啟動

該接口有兩個實現,分別是

org.springframework.boot.loader.archive.ExplodedArchive org.springframework.boot.loader.archive.JarFileArchive

前者用于在文件夾目錄下尋找資源,后者用于在jar包環境下尋找資源。而在SpringBoot打包的fatJar中,則是使用后者JarFileArchive

JarFile

JarFile:對jar包的封裝,每個JarFileArchive都會對應一個JarFile。

JarFile被構造的時候會解析內部結構,去獲取jar包里的各個文件或文件夾,這些文件或文件夾會被封裝到Entry中,也存儲在JarFileArchive中。如果Entry是個jar,會解析成JarFileArchive。

比如一個JarFileArchive對應的URL為:

jar:file:/Users/format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/

它對應的JarFile為:

/Users/format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar

這個JarFile有很多Entry,比如:

META-INF/META-INF/MANIFEST.MFspring/spring/study/....spring/study/executablejar/ExecutableJarApplication.classlib/spring-boot-starter-1.3.5.RELEASE.jarlib/spring-boot-1.3.5.RELEASE.jar...

JarFileArchive內部的一些依賴jar對應的URL(SpringBoot使用org.springframework.boot.loader.jar.Handler處理器來處理這些URL):

jar:file:/Users/Format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/lib/spring-boot-starter-web-1.3.5.RELEASE.jar!/

jar:file:/Users/Format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar!/lib/spring-boot-loader-1.3.5.RELEASE.jar!/org/springframework/boot/loader/JarLauncher.class

我們看到如果有jar包中包含jar,或者jar包中包含jar包里面的class文件,那么會使用 !/ 分隔開,這種方式只有org.springframework.boot.loader.jar.Handler能處理,它是SpringBoot內部擴展出來的一種URL協議。

Spring Boot如何通過java -jar啟動

JarLauncher工作流程

從MANIFEST.MF可以看到Main函數是JarLauncher,下面來分析它的工作流程。JarLauncher類的繼承結構是:

class JarLauncher extends ExecutableArchiveLauncherclass ExecutableArchiveLauncher extends Launcher

Launcher for JAR based archives. This launcher assumes that dependency jars are included inside a /BOOT-INF/lib directory and that application classes are included inside a /BOOT-INF/classes directory.

什么意思呢?

按照定義,JarLauncher可以加載內部/BOOT-INF/lib下的jar及/BOOT-INF/classes下的應用class。

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

其主入口新建了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加載。

Spring Boot如何通過java -jar啟動

小結 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.

到此這篇關于Spring Boot如何通過java -jar啟動的文章就介紹到這了,更多相關SpringBoot java -jar啟動內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美三级精品| 群体交乱之放荡娇妻一区二区| 国产在线日韩| 国产一区久久| 美女少妇全过程你懂的久久| 天堂av在线| 日韩三区免费| 91精品福利| 免费看的黄色欧美网站| 日韩制服丝袜先锋影音| 亚洲另类av| 日韩一区二区三区高清在线观看 | 国产伦一区二区三区| 日本午夜精品久久久| 亚洲tv在线| 欧美激情福利| 快播电影网址老女人久久| 欧美日韩激情| 蜜桃一区二区三区在线观看| 欧美亚洲综合视频| 国产精品99久久免费观看| 欧美韩一区二区| 欧美视频二区| 鲁鲁在线中文| 日韩精品欧美激情一区二区| 亚洲午夜精品久久久久久app| 亚洲精品一区二区在线看| 亚洲有吗中文字幕| 国产精品115| 欧美黄色网页| 蜜桃视频免费观看一区| 国产情侣久久| 日韩精品第二页| 日韩成人精品一区二区| 亚洲成人免费| 国产日韩欧美中文在线| av中文资源在线资源免费观看| 不卡视频在线| 欧美一区不卡| 精品日韩在线| 激情91久久| 国产精品亚洲二区| 激情久久中文字幕| 欧美一区激情| 亚洲手机视频| 国产精品一区毛片| 久久视频国产| 日韩高清不卡在线| 日韩高清中文字幕一区二区| 亚洲精品在线a| 日韩电影免费在线观看| 亚洲精品精选| 欧产日产国产精品视频| 手机精品视频在线观看| 丝袜美腿一区二区三区| 老司机免费视频一区二区| 日韩亚洲在线| 精品日韩一区| 日韩亚洲精品在线观看| 日韩成人亚洲| 国产日韩视频在线| 91久久中文| 精品一区二区三区视频在线播放 | 成午夜精品一区二区三区软件| 亚洲欧美日韩高清在线| 免费一区二区三区在线视频| 尤物在线精品| 福利视频一区| 巨乳诱惑日韩免费av| av在线最新| 欧美精品影院| 国产毛片久久| 国产欧洲在线| 国产伦理久久久久久妇女| 日韩视频不卡| 欧美日韩精品免费观看视完整| 欧美一区自拍| 午夜亚洲福利在线老司机| 日韩成人精品一区| 欧美一级一区| 丝袜脚交一区二区| 久久亚洲专区| 成人在线免费观看91| 最新国产精品久久久| 色老板在线视频一区二区| 国产精品视频一区二区三区综合| 欧美综合另类| 亚洲免费福利| 国产精品久久久久久久免费软件| 丝袜脚交一区二区| 蜜桃tv一区二区三区| 91日韩免费| 国产日韩一区二区三区在线 | 日韩在线电影| 国产午夜精品一区二区三区欧美 | 欧美13videosex性极品| 欧美日韩 国产精品| 亚洲一区二区三区四区电影| 久久视频精品| 六月婷婷综合| 久久精品国产网站| 国产日韩一区二区三区在线播放| 亚州国产精品| 99视频精品视频高清免费| 国产日韩亚洲| 91欧美日韩| 国产一区二区三区成人欧美日韩在线观看| 免费精品视频| 不卡在线一区| 亚洲a在线视频| 九九精品调教| 欧美三级精品| 国产精品精品| 福利视频一区| 亚洲日本网址| 国产综合亚洲精品一区二| 国产91一区| 日韩理论片av| 日韩久久一区二区三区| 成人精品中文字幕| 久久久久久久久久久9不雅视频| 黄在线观看免费网站ktv| 国产不卡精品| 国产91在线精品| 日本午夜大片a在线观看| 亚洲欧洲美洲av| 黄色在线网站噜噜噜| 国产成人在线中文字幕| 精品少妇一区| 国产精品一区二区av交换| 欧美日韩一区自拍| 欧美国产另类| 精品一区二区三区免费看| 国产suv精品一区二区四区视频| 精品视频在线一区二区在线| 六月丁香综合在线视频| 韩日一区二区| 成人在线视频免费| 韩国久久久久久| 久久精品电影| 日韩一级欧洲| 日本一区中文字幕| 国产麻豆精品| 久久久久久久欧美精品| 电影91久久久| 91视频一区| 91精品精品| 婷婷综合激情| 国产精品美女久久久| 免费在线观看成人| 日本色综合中文字幕| 国产精品传媒麻豆hd| 神马午夜在线视频| 欧美日韩国产精品一区二区亚洲| 视频在线在亚洲| 国产日产高清欧美一区二区三区| 中文字幕一区二区三区日韩精品| 日本欧美一区| 国产精品高颜值在线观看| 99精品美女| 免费在线看一区| 国产精品久久久久久模特| 国产精品毛片一区二区在线看| 激情欧美一区二区三区| 一区二区三区午夜视频| 国产伦精品一区二区三区在线播放 | 久久精品国产68国产精品亚洲| 国产中文一区| 日本亚洲视频| 久久国产三级| 日韩精品第一区| 在线看片日韩| 黄色精品视频| 亚洲精品极品少妇16p| 久久狠狠亚洲综合| 久久久夜精品| 一本一道久久a久久| 久久国产日韩欧美精品| 久久人人97超碰国产公开结果| 狠狠色狠狠色综合日日tαg| 91嫩草精品| 午夜精品久久久久久久久久蜜桃| 亚洲欧美日本日韩| 免费一级欧美在线观看视频| 国产高潮在线| 在线观看一区| 欧美日韩国产v| 中文无码日韩欧| 日韩大片免费观看| 伊人精品久久| 亚洲欧洲高清| 日韩一区二区三区精品 | 午夜精品成人av| 色婷婷成人网| 国产精品国产三级国产在线观看| 久久尤物视频| 久久亚洲欧洲| 久久精品人人| 麻豆精品91| 岛国av免费在线观看|