Maven和java的包管理
目录
什么是Maven
Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。
Maven 也可被用于构建和管理各种项目,例如 java,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。
包的概念
在java的概念中,包就是一些被用于某些功能的类的集合,把各种类打包压缩在一个文件中,表现为jar包war包等形式。
- JVM的工作被设计地相当简单
- 执行一个类的字节码
- 假如执行过程中碰到了该类引用的其他类,就找到它并加载它。
去哪里加载包中的类
类路径Classpath
答案是通过-classpath/-cp可以找到JVM加载运行的每一个类,它们在classpath中以 : 分隔。
如何确定一个类
利用类的全限定类名(目录层级)可以唯一确定一个类。
什么是包管理
包管理的本质就是告诉JVM去哪里寻找第三方类,然后如何解决其中的版本冲突问题。
Maven 一个跨时代的包管理程序
- Maven的包按照约定为所有的包编号,方便检索
- 扩展:语义化版本
- 在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的包越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。
- 版本语义化就是依赖地狱的解决方案之一,例如
- 语义化版本 x.y.z 主版本号.次版本号.修订号,遵循版本号递增规则
x是主版本号:当你做了不兼容的 API 修改,y是次版本号:当你做了向下兼容的功能性新增,z是修订号:当你做了向下兼容的问题修正。
Maven的坐标
关于坐标,我们最早的认知应该是平面几何中的二维坐标系(x,y),这样可以通过一个坐标唯一确定一个点。Maven也是利用坐标唯一确定一个包,坐标是Maven依赖管理的基础,Maven的中央仓库里拥有无数的jar或war包,通过项目中的pom.xml
文件引入Maven依赖,Maven的坐标元素常用的有<groupId><artifactId><version><packaging>
等等,利用这些坐标可以轻松的确定一个包,以前需要什么包就去什么网站寻找的日子一去不复返了。
在我们开发项目的时候,我们要严格写入坐标,这样Maven才可以正确的注入依赖。
Maven传递性依赖的解决
何为传递性依赖
简单来说就是某个项目添加的第三方依赖中又依赖了其他的第三方依赖。
传递性依赖的⾃动管理
- 原则上绝对不允许最终的classpath中出现同名不同版本的jar包。
依赖冲突的解决
- 原则:最近的胜出
- 举个例子:
- 图中C的jar有两个版本,由于0.2版本离项目比较近,所以优先使用C的0.2版本。
- 假如你一定要使用C的0.1版本,那么需要做以下操作之一:
- 在pom.xml中重新添加依赖,添加到依赖树
mvn dependency:tree
离你的项目相对更近的位置。 - 在pom.xml中D的依赖标签中加入
<exclusions>
标签声明排除C的0.2版本。
- 在pom.xml中重新添加依赖,添加到依赖树
依赖的scope
Maven的依赖范围在xml文件中用<scope>
表示,参数有以下:
compile
:编译依赖。如果没有手动指定,那么就默认使用该参数,对于编译、测试、运行的三种classpath都有效。test
:测试依赖。只对于测试classpath的范围有效,但是在编译代码或者运行项目时无效。provide
:已提供依赖。别的容器(Web Container)会提供,对于编译、测试的classpath有效,对运行无效。runtime
:运行时依赖。对于测试、运行时的classpath有效,但在编译代码时无效。system
:系统依赖。从参与度来说,也provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用。import
:导入依赖。略
当你看到如下异常,大概率是发生了包冲突
- AbstractMethodError
- NoClassDefFoundError
- ClassNotFoundException
- LinkageError
值得一提的是Maven还是优秀的自动化构建工具
Maven的生命周期
阶段 | 处理 | 描述 |
---|---|---|
验证 validate | 验证项目 | 验证项目是否正确且所有必须信息是可用的 |
编译 compile | 执行编译 | 源代码编译在此阶段完成 |
测试 Test | 测试 | 使用适当的单元测试框架(例如JUnit)运行测试。 |
包装 package | 打包 | 创建JAR/WAR包如在 pom.xml 中定义提及的包 |
检查 verify | 检查 | 对集成测试的结果进行检查,以保证质量达标 |
安装 install | 安装 | 安装打包的项目到本地仓库,以供其他项目使用 |
部署 deploy | 部署 | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程 |