前言
最近又在研究 SpringBoot 源碼(研究好幾次了,研究完有些用不上就忘了😅),在 SpringBoot 執行 main 方法啟動過程中,會根據 classpath 下的類信息推斷當前環境信息。這里 classpath 究竟是指哪呢,搜了中文語境下的技術文章,竟然沒有找到想要的回答,可能是問題太簡單了。本篇記錄下我的看法。
java 最基礎的 classpath
classpath,顧名思義,就是指 .class 文件所在的路徑。.class 文件由 .java 文件編譯后產生,我們用 java 命令執行.class 文件時,需要指定 jvm 去哪搜索目標 class 文件,總不能全盤掃描對吧,而指定去哪搜索就是 classpath 的含義,即:
classpath
是JVM用到的一個環境變量,它用來指示JVM如何搜索class
。
執行 java 命令時,通過java -classpath dir
或者簡寫為 java -cp dir
來指定,
如果命令中沒有顯式指定,則 jvm 在當前目錄中查找,即默認為:java -cp .
。
可以在命令中指定多個classpath,Linux 下用:
分隔。jvm 會依次查找指定目錄,查找到一個之后不再繼續查找下一個,比如java -cp .:/usr/local:/tmp/work
。
jar 包的 classpath
我們工程中一般都會有很多 .class 文件,利用 jar 包可以將他們批量管理起來,像這樣java -cp ./demo.jar boo.Helloworld
指定 jar 包為 classpath 的話,jvm 就會去這個 jar 包里面搜索需要的類。
jar包還可以包含一個特殊的/META-INF/MANIFEST.MF
文件,MANIFEST.MF
是純文本,可以指定Main-Class
和其它信息。JVM會自動讀取這個MANIFEST.MF
文件,如果存在Main-Class
,我們就不必在命令行指定啟動的類名,而是用更方便的命令:
java -jar hello.jar
jar包還可以包含其它jar包,這個時候,就需要在MANIFEST.MF
文件里配置classpath
了。
在大型項目中,不可能手動編寫MANIFEST.MF
文件,再手動創建zip包。Java社區提供了大量的開源構建工具,例如Maven,可以非常方便地創建jar包。
SpringBoot 特殊的 classpath
我們將一個基於 SpringBoot 和 Maven 開發的工程打成 jar 包,然后解壓,可以看到這樣的目錄結構:
其中/META-INF/MANIFEST.MF
就是我們上文所述的可以指定Main-Class
的文件,我們打開看一下:
其中Main-Class
標識 SpringBoot 項目啟動時,使用了自己的類JarLauncher
來加載 jar 包;
Spring-Boot-Classes
指定了 SpringBoot 項目的業務代碼的文件夾路徑;
Spring-Boot-Lib
指定了 SpringBoot 項目依賴的 jar 包的文件夾路徑
我們打開文件夾進行驗證,果然如此,SpringBoot 項目看來對搜索 jar 包的規則進行了改造:
在 IDEA 中啟動應用時的 classpath
在 IDEA 等工具中運行 java 程序時,IDEA幫我們用命令行傳入了我們依賴的所有 jar 包,這是我項目的命令,可以看出來非常多:
點開下圖這行灰色的就能看到完整命令了:
參考
https://www.liaoxuefeng.com/wiki/1252599548343744/1260466914339296