mvn dependency:list:查看当前项目所有依赖。 mvn dependency:tree:以树的形式显示当前项目的所有依赖,相比mvn dependency:list 列表显示,能很清楚的看到某个依赖是通过哪条依赖路径引入的。 mvn dependency:analyze:分析项目的依赖关系,并确定哪些依赖是:使用和声明、使用和未声明、未使用和声明。
如有依赖关系为A->B->C,A依赖B,称为直接依赖。A本身不依赖C,但C通过B传递给A,称C为A的传递性依赖。
通过mvn dependency:list查看A项目的依赖列表,可以看到依赖B和C:
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ A ---
[INFO]
[INFO] The following files have been resolved:
[INFO] com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile
[INFO] junit:junit:jar:3.8.1:test
[INFO] com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
路径1:A->B->C(version:1.0) 路径2:A->D->E->C(version:2.0) 通过两条依赖路径可以看出,A的传递性依赖的C有两个不同版本,为了避免依赖重复,最终只能选择一个。这种情况Maven采用路径最近者优先的原则来处理,路径1中C到A的距离比路径2中C到A的距离要短,于是路径1中C(version:1.0)最终被A依赖。
mvn dependency:tree 查看依赖路径:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A ---
[INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT
[INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:E:jar:0.0.1-SNAPSHOT:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
路径1:A->B->C(version:1.0) 路径2:A->D->C(version:2.0) 路径1和路径2中C到A的距离是相同的,通过路径最近者优先原则无法判断该使用哪个依赖,此时Maven会使用第一声明者优先原则进行选择,第一声明者优先原则是指在POM依赖中声明顺序最靠前的那个依赖会被选择。在A的POM文件中B的声明靠前,于是C(version:1.0)会被选择。
<!-- A的pom.xml中依赖部分-->
<dependencies>
<dependency>
<groupId>com.nocoffee</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.nocoffee</groupId>
<artifactId>D</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
mvn dependency:tree 查看依赖路径:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A ---
[INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT
[INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile
[INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
在场景2中,如果要使A依赖C(version:2.0) ,则可以配置排除依赖:
<dependencies>
<dependency>
<groupId>com.nocoffee</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<!-- 排除依赖 C -->
<exclusion>
<groupId>com.nocoffee</groupId>
<artifactId>C</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.nocoffee</groupId>
<artifactId>D</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
mvn dependency:tree 查看依赖路径,A不再通过B依赖C,而是通过D依赖C:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A ---
[INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT
[INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile
[INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
以场景2为例,可以在B的pom.xml里将C配置为可选依赖,使A依赖D的C(version:2.0)。
<!-- B的pom.xml -->
<dependency>
<groupId>com.nocoffee</groupId>
<artifactId>C</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 设置可选依赖 -->
<optional>true</optional>
</dependency>
mvn dependency:tree 查看依赖路径,A不再通过B依赖C,而是通过D依赖C:
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A ---
[INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT
[INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile
[INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile
[INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
每个范围(import导入依赖范围除外)以不同方式影响传递依赖性,如下表所示。以A->B->C依赖路径为例,左边第一列为第一直接依赖(B在A中的依赖范围),最上面一行为第二直接依赖(C在B中的依赖范围),交叉单元格为传递性依赖范围(C在A中的依赖范围)。
compile | provided | runtime | test | |
---|---|---|---|---|
compile | compile(*) | - | runtime | - |
provided | provided | - | provided | - |
runtime | runtime | - | runtime | - |
test | test | - | test | - |