Maven 依赖管理

引入依赖

在maven引入jar依赖是通过:
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
    </dependency>
 </dependencies>

* 详情可参考:
  https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

依赖范围

  • 什么是依赖范围
    在依赖包时,这些依赖的包怎么引入,引入之后作用在什么时候。这些就是依赖范围需要明确的,换句话说就是作用域。作用域范围就是classpath,maven将其划分成: 编译classpath, 测试classpath, 运行时classpath。根据定义的依赖范围来确认jar依赖最终引入到哪个classpath。
  • 有哪些依赖范围
scope编译classpath测试classpath运行classpath
compileYYY
testNYN
providedYYY
runtimeNYY
systemYYN
默认scope=compile,相应引入的jar包,会加入到这三个classpath中;
* test:表示该jar包只是执行单元测试时使用,因此只需要引入到测试classpath即可;例如:junit包
* provided: 表示已经提供了,啥意思呢,意思就是在你运行的时候,这个已经提供好了,不需要你引入,只是在你编译或者测试时,需要引入。典型的就是servlet-api,为了正常编译和测试,我们通常会引入该包,但是在运行时,由于tomcat等容器已经提供了,并将相应的servlet-api包加载到了WEB-INF/lib。因此其只作用在编译classpath、测试classpath;
* runtime: 表示运行时引入,最直接会引入到运行时classpath, 不过这里也会引入到测试classpath,个人理解是因为在测试时,实际上会执行相应的代码逻辑,如果这段代码逻辑实际使用到了这个包,那么务必是需要引用的,因此也会作用在测试classpath,但是编译并不执行,只要接口ok,就不需要引入具体的实现包,典型:引入jdbc驱动,在编译时,并没有使用到具体的驱动实现包,但是在测试、运行时,需要使用;
* system: 这个的作用和provided基本一致,唯一的差别其引用不是通过maven进行解析的,而是通过设置systemPath 文件路径来引入的。
如何选择scope,关键在于期望哪个阶段(编译、测试、运行)使用包,然后再根据scope对应作用的classpath,从而确认scope的类型。

传递性依赖

  • 什么是传递性依赖
所谓的传递性依赖,就是: A -> B -> C (其中,A依赖B,B依赖C),需要确认的是A->C之间的依赖情况。
依赖传递,可以减少依赖包的申明,简化依赖配置;但是也带来了新一些新问题。
  • 依赖传递方式
引入依赖时,需要确认依赖范围(默认compile),例如:A->B(compile),B->C(compile),那么A->C的依赖范围是怎样的?这是急需定义和解决的问题。
A -> B \ B->Ccompiletestprovidedruntimesystem
compilecompileruntime
testtesttest
providedprovidedprovidedprovidedprovided
runtimeruntimeruntime
systemsystemsystemsystemsystem
案例:maven-hello(A) , maven-common(B) , junit(C)
  • A->B(compile) + B->C(compile) => A - C (compile)
**maven-hello(A)**
<dependencies>
    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
</dependencies>
**maven-hello(B)**
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>compile</scope>
        </dependency>
</dependencies>

这里写图片描述

现象:maven-hello 依赖 maven-common 范围是 compile, maven-common 依赖 junit 范围是 compile, 发现 maven-hello 依赖 junit 范围 compile;
  • A->B(compile) + B->C(test) => A - C (no relation)
**maven-hello(A)**
<dependencies>
    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
</dependencies>
**maven-hello(B)**
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
</dependencies>

这里写图片描述

现象:maven-hello 依赖 maven-common 范围是 compile, maven-common 依赖 junit 范围是 test, 发现 maven-hello 与 junit 无任何关系;
  • A->B(compile) + B->C(provided) => A - C (no relation)
**maven-hello(A)**
<dependencies>
    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
</dependencies>
**maven-hello(B)**
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>provided</scope>
        </dependency>
</dependencies>

这里写图片描述

现象:maven-hello 依赖 maven-common 范围是 compile, maven-common 依赖 junit 范围是 provided, 发现 maven-hello 与 junit 无任何关系;
  • A->B(compile) + B->C(runtime) => A -> C (runtime)
**maven-hello(A)**
<dependencies>
    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
</dependencies>
**maven-hello(B)**
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>runtime</scope>
        </dependency>
</dependencies>

这里写图片描述
这里写图片描述
这里写图片描述

现象:maven-hello 依赖 maven-common 范围是 compile, maven-common 依赖 junit 范围是 provided, 发现 maven-hello 依赖 junit 范围为 runtime ( 执行 mvn compile, mvn test 都会报错,但是执行mvn surefire:test 不会错,因为mvn test 执行了compile,找不到org.junit前提是代码中使用到了,这是因为包没有引入);
类似上述操作,其他情况可以逐一尝试,这里不做所有举例。 思路大概就是:
依赖关系的依赖范围,决定了这些包该引入到哪个classpath,如果A->B,根据scope确认了B将被引入到A的哪个classpath,然后再推进B->C,如果A存在直接使用C的情况,那么就会出现直接依赖,如果没有那么A与C之间可以认为是没有关系。
  • 依赖带来的问题
上面介绍的单个路径依赖,多出现多个路径依赖时,该如何进行依赖选择呢?

case1:

A -> B ->C -> X(1.0) && A -> D -> X(2.0),maven采用最短路径方式选择;
1A -> B ->C -> X(1.0) ,路径是3 
2A -> D -> X(2.0),路径是2;
那么选择路径为2X(2.0),这里不具体通过实例展示,有兴趣的可以,实现下。

case2:

如果路径相同时,那该如何选择呢?
A ->B -> X(1.0) && A -> C -> X(2.0),maven采取谁先申明谁优先的原则;
假设,B先申明,那么会选择X(1.0),反之X(2.0);
举例:
1、maven-hello -> maven-common -> junit(4.10)
2、maven-hello -> maven-base -> junit(4.12)

maven-hello

<dependencies>

    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-base</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>

    <dependency>
      <groupId>study.wzp.maven</groupId>
      <artifactId>maven-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>

  </dependencies>

maven-common

 <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>compile</scope>
        </dependency>
</dependencies>

maven-base

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
</dependencies>
现象:maven-hello 依赖 junit(4.12) ,如果把pom.xml的依赖顺序,将maven-common提前,那么依赖的是junit;

这里写图片描述

先进行路径依赖长度判断,如果长度一样再使用优先配置选择(这种方式,支持maven2.0.9之后的版本)

依赖分析手段

    通常我们在构建项目,配置依赖时,难免出现过多依赖等不合理的依赖,可以通过一些命令来帮助查看依赖情况。
  • mvn dependency:list
列出依赖列表,例如:
[INFO] The following files have been resolved:
[INFO]    study.wzp.maven:maven-base:jar:1.0-SNAPSHOT:compile
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:compile
[INFO]    study.wzp.maven:maven-common:jar:1.0-SNAPSHOT:compile
[INFO]    junit:junit:jar:4.12:compile
  • mvn dependency:tree
树形结构展示依赖列表:
[INFO] study.wzp.maven:maven-hello:pom:1.0-SNAPSHOT
[INFO] +- study.wzp.maven:maven-base:jar:1.0-SNAPSHOT:compile
[INFO] |  \- junit:junit:jar:4.12:compile
[INFO] |     \- org.hamcrest:hamcrest-core:jar:1.3:compile
[INFO] \- study.wzp.maven:maven-common:jar:1.0-SNAPSHOT:compile
  • mvn dependency:analyze
分析依赖情况,可以找出一些不合理的依赖。
INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ maven-hello ---
[WARNING] Unused declared dependencies found:
[WARNING]    study.wzp.maven:maven-base:jar:1.0-SNAPSHOT:compile
[WARNING]    study.wzp.maven:maven-common:jar:1.0-SNAPSHOT:compile
[INFO] ------------------------------------------------------------------------
标识申明了junit,但是没有使用,类似这种提示处理。
依赖分析详情参考:https://maven.apache.org/components/plugins/maven-dependency-plugin/ 

参考

[1] https://maven.apache.org/components/plugins/maven-dependency-plugin/

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值