20中级 - Java的包管理与Maven初步

314 阅读4分钟

Java的包原理

  • JVM的工作被设计地相当简单:
    • 执行一个类的字节码
    • 假如这个过程中碰到了了新的类,加载它
  • 那么,去哪⾥里里加载这些类呢?
    • 在类路径(ClassPath)中挨个找,如果是文件夹就继续挨个找下去,如果碰到的是jar包就解压缩出来看看,能不能找到

类路径

  • 在哪⾥里里可以找到类
    • classpath/-cp
  • 类的全限定类名(⽬目录层级)唯⼀一确定了了⼀一个类
  • 包就是把许多类放在⼀一起打的压缩包,jar包就是一堆类的集合

jar包什么时候下载

  • 按需下载,什么时候需要什么时候下载,比如compile需要就compile的时候下载,test的时候需要就test的时候下载

传递性依赖

  • 你依赖的类还依赖了了别的类
  • 如果两个包里都有github.com.a这个类,那么谁在前面最后调用谁,
  • 和命令行执行顺序一样,恐怖的点是同名但是代码不一样

Classpath hell

  • 全限定类名是类的唯⼀一标识
  • 当多个同名类同时出现在Classpath中,就是噩梦的开始

什么是包管理

  • 你要使⽤用⼀一些第三⽅方类,总要告诉JVM从哪⾥里里找吧?
  • 包管理理的本质就是告诉JVM如何找到所需的第三⽅方类库
  • 以及成功地解决其中的冲突问题

在没有maven的年代

  • 手动管理写命令编译,黑暗岁月

启蒙时代

  • Apache Ant
    • 手动下载jar包,放在⼀个目录中
    • 写XML配置,指定编译的源代码⽬目录、依赖的jar包、输出目录等
  • 缺点
    • 每个⼈人都要⾃自⼰己造⼀一套轮⼦子
    • 依赖的第三⽅类库都需要手动下载,费时费⼒
    • 假如你的应⽤依赖了了一万个第三方的类库呢?
      • 没有解决Classpath地狱的问题

Maven——划时代的包管理理

  • Convention over configuration
    • 约定优于配置
  • 必须强调,Maven远远不不⽌是包管理工具
  • Maven的中央仓库
    • 按照⼀定的约定存储包
  • Maven的本地仓库
    • 默认位于~/.m2
    • 下载的第三⽅包放在这⾥进行缓存

maven-划时代的包管理工具

  • maven的包,按照约定为所有的包编号方便检索
    • 约定了三个要素,groupId,artifactId,version
    • groupId有点像一个组织,所有的组织的包都放在一起
    • artifactId,组织下不同的功能,比如有仓库,订单,购物车,对应不同的包,
    • 包有不同版本version,一旦发布了无法撤销只能升级
  • maven的包管理完爆隔壁go语言的15条街
  • 根据pom将传递性依赖一个完整的树下载好
  • 默认情况下maven,只会下载字节码包,需要看源代码就店家download source
  • 语义化版本,版本号x.y.z,第一个x是主版本号,第二个y是次版本号,第三个z是修订号
  • snapshot,对于频繁变更,不稳定的版本,只用于两个团队快速开发,正式上线之后要变成一个正式版本
    • 一般也就公司内部有snapshot库,正式线上环境不会放
  • RC是release candidate准备发布版,M代表里程碑milestone 版本

实战解决包冲突

  • 包冲突异常的常见几种表现

    • AbstractMethodError
    • NoClassDefFoundError
    • ClassNotFoundException
    • LinkageError
  • 产生包冲突的原因

1.png

  • 传递性依赖的自动管理
    • 原则:绝对不允许最终的classpath出现同名不同版本的jar包
  • 依赖冲突的解决
    • 原则:最近的胜出 2.png
  • 依赖的scope

2.png

解决办法

  • 人肉解决
  • maven dependency:tree 查看依赖,也可以重定向到文件中maven dependency:tree > d.txt

3.png

  • 通过pom找到库的github地址,然后通过tag去进行切换,找到两个版本的区别,定位问题,这个步骤非常耗费精力
  • 解决办法1,直接强行依赖版本 4.png 5.png
  • 解决方案2

6.png

7.png

  • 解决方案3,使用插件maven helper

8.png

  • 相同距离谁靠前谁赢

9.png

Maven的其他知识

  • scope,最重要的scope有两个compile和test
  • test就表示这个库的作用范围只在test中,compile表示在compile和test中都有效
  • provided表示只在编译的时候有效,运行的时候就没有效果了,ide会编译和运行你的代码
    • 因此provided可以成功编译,但是不能够成功运行

maven相关书籍

  • maven 实战
  • pom就是project object model,项目说明书
  • pom字段解释,properties定义了属性,scm,source control management,源代码管理,profile指定环境