java代码的执行是从将人所编写的代码编译为JVM所执行的机器码开始的。
用import引入包的操作标记了包的地址,而当JVM读到包名时会从包的地址找到包本身,然后执行包中的代码
当然JVM的寻找并不是说把整个项目全部找个遍。当我们在是使用maven进行包管理时,
我们使用maven指令来启动项目,其中maven帮我们填写了执行指令中的执行参数,
参数中 -classpath参数就是用来告诉了JVM去哪些目录下去寻找包,并告诉了JVM搜索的先后顺序,
参数中地址与地址用 ":" (Linus) / ";" (Windows)来分离,按排列顺序先后来进行搜索。
我们可以仔细观察控制台看到,实际执行的启动指令最后有一长串看起来像是很多项目地址名的拼接,
我们复制出来能看到都是 -classpath的参数。
而maven之所以知道第三方包的来源都是通过项目根目录下的pom文件来配置包依赖,
包括第三方包中对其他第三方包的依赖也是通过在第三方包中的pom文件配置,
然后maven读取pom文件的配置来进行管理的。
当发生包冲突时不同项目管理工具的默认处理方式
maven
存在同一个依赖,版本不同的包时,
选取依赖层次最浅的,最靠前的包
gradle
存在同一个依赖,版本不同的包时,
选择最新版本的包
不同的包管理工具的默认的包冲突的处理策略可能不一样
maven的使用原则是基于约定大于配置的
maven的默认配置文件是储存在super pom中的
这个配置文件压缩在maven-model-builder-x.x.x.jar文件中
这个压缩文件可以在maven安装目录下的lib文件夹中找到
我们把这个文件解压缩(文件后缀改为压缩文件后缀即可使用正常解压缩)后
在org\apache\maven\model\下可以找到 pom-4.0.0.xml文件
所有项目文件的pom都继承于这个super pom
在配置项目的 pom.xml 的时候,只需要配置项目所需要的参数
默认遵守约定,即不覆写super pom的参数
maven不仅管理第三方包,也负责告诉JVM依赖的位置
当第三方包发生重复或是发生冲突时,
maven会按照依赖层次来选择依赖包来避免实际编译时发生冲突,并忽略重复的依赖
我们也可以通过exception来告诉maven不选取哪些依赖下的子依赖,来避免依赖冲突
当我们在项目根目录下的pom.xml中配置依赖后,
maven会依照依赖配置的groupId和artifactId定位包在中央仓库的位置
并按照version下载对应版本的包
maven可以替代人工来填写执行命令的项项参数,避免了过去手工填写-classpath的麻烦
maven 管理依赖的同时,也是项目管理工具
maven约定项目文件的结构即
参数 | 配置项 |
---|---|
目录src/main/java | java源码目录 |
目录src/main/resources | 资源文件目录 |
目录src/test/java | 测试java源码目录 |
目录src/test/resources | 测试资源文件目录 |
目录target | 打包输出目录 |
目录target/classes | 编译输出目录 |
目录target/test-classes | 测试编译输出目录 |
目录target/site | 项目site输出目录 |
目录src/main/webapp | web应用文件目录(当打包为war时),如WEB-INF/web.xml |
jar | 默认打包格式 |
*Test.java | Maven只会自动运行符合该命名规则的测试类 |
%user_home%/.m2 | Maven默认的本地仓库目录位置 |
Maven默认使用远程中央仓库:http://repo1.maven.org/maven2 | 中央仓库 |
在我们配置依赖时 我们可以通过scope来告诉maven依赖的使用范畴
默认为compile,即项目编译阶段就会使用
我们可以指定为test,即只在测试环境下进行编译运行,在正式运行并不会编译运行。
这样将测试依赖从正式运行环境中分离出来
网友评论