SpringBoot项目中的classpath到底指什么?

前言

最近又在研究 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 包,然后解压,可以看到这样的目录结构:

image-20210528150316369

其中/META-INF/MANIFEST.MF就是我们上文所述的可以指定Main-Class的文件,我们打开看一下:

image-20210528150704871

其中Main-Class标识 SpringBoot 项目启动时,使用了自己的类JarLauncher来加载 jar 包;

Spring-Boot-Classes指定了 SpringBoot 项目的业务代码的文件夹路径;

Spring-Boot-Lib指定了 SpringBoot 项目依赖的 jar 包的文件夹路径

我们打开文件夹进行验证,果然如此,SpringBoot 项目看来对搜索 jar 包的规则进行了改造:

image-20210528151119477

在 IDEA 中启动应用时的 classpath

在 IDEA 等工具中运行 java 程序时,IDEA帮我们用命令行传入了我们依赖的所有 jar 包,这是我项目的命令,可以看出来非常多:

image-20210528142255311

点开下图这行灰色的就能看到完整命令了:

image-20210528142356501

参考

https://www.liaoxuefeng.com/wiki/1252599548343744/1260466914339296

https://segmentfault.com/a/1190000015802324

posted @ 2021-06-18 16:27  孔令翰  阅读(3388)  评论(0编辑  收藏  举报