Maven的依赖(Dependency)

环境

  • 操作系统: Ubuntu 20.04
  • JDK: 17
➜  ~ java -version
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
  • Maven: 3.8.5
➜  ~ mvn -v
Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
Maven home: /home/ding/Downloads/apache-maven-3.8.5-bin/apache-maven-3.8.5
Java version: 17.0.1, vendor: Oracle Corporation, runtime: /home/ding/Downloads/jdk-17.0.1
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.13.0-39-generic", arch: "amd64", family: "unix"

背景

在Maven世界里,每一个构件(artifact)都有唯一的坐标(Coordinate)。坐标是用一系列元素来定义的:

  • groupId
  • artifactId
  • version
  • packaging
  • classifier

其中, groupIdartifactIdversion 是必需的, packaging 是可选的(默认值为 jar ),而 classifier 是不能直接定义的。

问题

在POM中,我们可以定义依赖关系,例如:

............
	<dependencies>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		............
	<dependencies>
............

被依赖的artifact(本例中是 spring-boot-starter-web ),显然也需要 groupIdartifactIdversion 来唯一标识,然而,这里只有 groupIdartifactId ,并没有 version 。这是怎么回事呢?

带着这个问题,我们来看一下Maven的依赖(dependency)。

聚合和继承

一个项目(project)的开发,通常采用“模块化开发”的方式,项目是由多个模块(module)所组成,模块秉承“高内聚,低耦合”的原则。例如开发团队分为多个小组,每组只专注于各自所负责的模块的开发和调试。但项目作为一个整体,需要在总体上进行管理和构建。

Maven提供了 聚合继承 这两个概念:

  • 聚合:把各个模块聚合在一起构建;
  • 继承:抽取各个模块相同的依赖和插件等配置,以简化配置,方便维护;

聚合

聚合比较简单,就是把多个模块在一起构建。例如,我们有 module1module2 两个模块。为了把它们聚合在一起,我们再创建一个额外的 aggregator 模块。该模块本身作为一个Maven项目,有自己的pom文件,但是它不涉及项目的具体业务逻辑,所以没有src等目录。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<groupId>com.example.demo0402groupId>
	<artifactId>aggregatorartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<packaging>pompackaging>
	<name>Aggregatorname>
	<modules>
		<module>module1module>
		<module>module2module>
	modules>
project>

该POM的核心配置是:

  • packaging :必须是 pom
  • modules :要聚合的模块。注意此处的每一个值都是针对当前pom文件的相对路径。通常可以令目录名与其artifact名一致,以便于理解和快速定位,不过也不强制,反正记住这里要写目录名;

一般我们把聚合模块作为module1、module2等模块的父一级目录,即:

➜  test0402 tree
.
└── aggregator
    ├── module1
    │   ├── pom.xml
    │   └── src
    │       ├── main
    │       │   ├── java
    │       │   └── resources
    │       └── test
    │           └── java
    ├── module2
    │   ├── pom.xml
    │   ├── src
    │   │   ├── main
    │   │   │   ├── java
    │   │   │   └── resources
    │   │   └── test
    │   │       └── java
    └── pom.xml

在build aggregator 的时候,可以看到构建的细节,例如:

➜  aggregator mvn clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] module1                                                            [jar]
[INFO] module2                                                            [jar]
[INFO] Aggregator                                                         [pom]
............
[INFO] Reactor Summary for Aggregator 0.0.1-SNAPSHOT:
[INFO] 
[INFO] module1 ............................................ SUCCESS [ 11.691 s]
[INFO] module2 ............................................ SUCCESS [  4.185 s]
[INFO] Aggregator ......................................... SUCCESS [  0.060 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  16.123 s
[INFO] Finished at: 2022-04-03T17:48:02+08:00
[INFO] ------------------------------------------------------------------------

注意上面显示的是各个模块的 name ,而不是 artifactId

继承

module1module2 模块有很多相同的配置,比如 groupIdversion ,此外还有 spring-boot-starter-web 等三方依赖包也一样。重复的配置显然增加了维护成本,并带来潜在的不一致风险。

Maven提供了继承机制,来抽取重复的配置。这有点类似于面向对象的父子类关系,在父POM中定义一些配置以供子POM来继承。

“父POM”与“聚合POM”有些相似之处:

  • POM的 packaging 必须为 pom
  • 不需要src目录;

aggregator 目录下创建一个 parent 目录,然后在 parent 目录里创建 pom.xml 文件,内容如下:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<groupId>com.example.demo0402groupId>
	<artifactId>parentartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<packaging>pompackaging>
	<name>Parentname>
project>

有了父模块, module1module2 还必须显式的声明继承关系。

module1 为例,在其pom.xml文件中添加如下内容:

	<parent>
		<groupId>com.example.demo0402groupId>
		<artifactId>parentartifactId>
		<version>0.0.1-SNAPSHOTversion>
		<relativePath>../parent/pom.xmlrelativePath>
	parent>

module1 可以删除自己的 groupIdversion 设置,默认会从父模块继承。这样,就可以确保各个模块始终保持相同的 groupIdversion

注: relativePath 的默认值是 ../pom.xml ,即上一级目录。

接下来,我们来把dependency抽取到父模块。

若直接把子模块中公共的dependency配置移到父模块,固然OK,不过这种做法存在一个问题,如果以后再有新的子模块(如 module3 ),而新的子模块并不需要这些dependency,这就难办了。

所以Maven提供了 dependencyManagement 元素。

  • 在父模块中通过 dependencyManagement 元素声明dependency;
  • 在子模块中通过 dependency 元素引用所需的dependency;

在父模块POM中添加如下内容:

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-starter-webartifactId>
				<version>2.6.6version>
			dependency>
		dependencies>
	dependencyManagement>

在子模块POM的 dependencies 中添加如下内容:

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>

我们看到,子模块的dependency只需指明 groupIdartifactId ,而无需指定 version 。这是因为完整的dependency信息是在父模块的 dependencyManagement 定义的,所以子模块只需通过 groupIdartifactId 来引用即可。

这种做法的好处是:

  • 统一性:所有dependency都由父模块统一定义,确保子模块使用的dependency版本一致;
  • 灵活性:子模块只需引用自己所需的dependency;

有一种特殊的依赖范围( scope ),叫做 import 。这种依赖通常指向一个POM,作用是将其 dependencyManagement 配置导入到当前的POM中。例如:

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.example.demo0402groupId>
				<artifactId>xxxartifactId>
				<version>0.0.1-SNAPSHOTversion>
				<type>pomtype>
				<scope>importscope>
			dependency>
			<dependency>
				<groupId>com.example.demo0402groupId>
				<artifactId>yyyartifactId>
				<version>0.0.1-SNAPSHOTversion>
				<type>pomtype>
				<scope>importscope>
			dependency>
			............
		dependencies>
	dependencyManagement>

常见做法是把依赖根据类型不同,生成多个POM(如上例中的 xxxyyy 等),然后在父模块中将其一一导入,以便“分而治之”。

聚合与继承的关系

共同点

  • packaging 必须是 pom
  • 除了POM外并无src等实际内容;

区别

聚合 继承
目的 为了方便快速构建整个项目 为了消除重复配置
关系 聚合POM知道被聚合的POM;被聚合的POM不知道聚合POM 父POM不知道子POM;子POM知道父POM
关键字 modules / module (父) parent (子), dependencyManagement (父)

集成

为了方便,通常可以把聚合POM和父POM合二为一,只用一个POM。具体例子参见代码。

代码

https://github.com/dukeding/test0402

查看依赖

常用命令:

  • mvn dependency:list
  • mvn dependency:tree
  • mvn dependency:analyze

mvn dependency:list

该命令可以查看依赖。例如:

➜  aggregator git:(main) ✗ mvn dependency:list
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Aggregator                                                         [pom]
[INFO] module1                                                            [jar]
[INFO] module2                                                            [jar]
[INFO] 
[INFO] ------------------< com.example.demo0402:aggregator >-------------------
[INFO] Building Aggregator 0.0.1-SNAPSHOT                                 [1/3]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:list (default-cli) @ aggregator ---
[INFO] 
[INFO] The following files have been resolved:
[INFO]    none
[INFO] 
[INFO] 
[INFO] --------------------< com.example.demo0402:module1 >--------------------
[INFO] Building module1 0.0.1-SNAPSHOT                                    [2/3]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:list (default-cli) @ module1 ---
[INFO] 
[INFO] The following files have been resolved:
[INFO]    org.springframework.boot:spring-boot-starter-web:jar:2.6.6:compile -- module spring.boot.starter.web [auto]
[INFO]    org.springframework.boot:spring-boot-starter:jar:2.6.6:compile -- module spring.boot.starter [auto]
[INFO]    org.springframework.boot:spring-boot:jar:2.6.6:compile -- module spring.boot [auto]
[INFO]    org.springframework.boot:spring-boot-autoconfigure:jar:2.6.6:compile -- module spring.boot.autoconfigure [auto]
[INFO]    org.springframework.boot:spring-boot-starter-logging:jar:2.6.6:compile -- module spring.boot.starter.logging [auto]
[INFO]    ch.qos.logback:logback-classic:jar:1.2.11:compile -- module logback.classic (auto)
[INFO]    ch.qos.logback:logback-core:jar:1.2.11:compile -- module logback.core (auto)
[INFO]    org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile -- module org.apache.logging.slf4j [auto]
[INFO]    org.apache.logging.log4j:log4j-api:jar:2.17.2:compile -- module org.apache.logging.log4j
[INFO]    org.slf4j:jul-to-slf4j:jar:1.7.36:compile -- module jul.to.slf4j (auto)
[INFO]    jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile -- module java.annotation [auto]
[INFO]    org.yaml:snakeyaml:jar:1.29:compile -- module org.yaml.snakeyaml [auto]
[INFO]    org.springframework.boot:spring-boot-starter-json:jar:2.6.6:compile -- module spring.boot.starter.json [auto]
[INFO]    com.fasterxml.jackson.core:jackson-databind:jar:2.13.2.2:compile -- module com.fasterxml.jackson.databind
[INFO]    com.fasterxml.jackson.core:jackson-annotations:jar:2.13.2:compile -- module com.fasterxml.jackson.annotation
[INFO]    com.fasterxml.jackson.core:jackson-core:jar:2.13.2:compile -- module com.fasterxml.jackson.core
[INFO]    com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.2:compile -- module com.fasterxml.jackson.datatype.jdk8
[INFO]    com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.2:compile -- module com.fasterxml.jackson.datatype.jsr310
[INFO]    com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.2:compile -- module com.fasterxml.jackson.module.paramnames
[INFO]    org.springframework.boot:spring-boot-starter-tomcat:jar:2.6.6:compile -- module spring.boot.starter.tomcat [auto]
[INFO]    org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.60:compile -- module org.apache.tomcat.embed.core
[INFO]    org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.60:compile -- module org.apache.tomcat.embed.el
[INFO]    org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.60:compile -- module org.apache.tomcat.embed.websocket
[INFO]    org.springframework:spring-web:jar:5.3.18:compile -- module spring.web [auto]
[INFO]    org.springframework:spring-beans:jar:5.3.18:compile -- module spring.beans [auto]
[INFO]    org.springframework:spring-webmvc:jar:5.3.18:compile -- module spring.webmvc [auto]
[INFO]    org.springframework:spring-aop:jar:5.3.18:compile -- module spring.aop [auto]
[INFO]    org.springframework:spring-context:jar:5.3.18:compile -- module spring.context [auto]
[INFO]    org.springframework:spring-expression:jar:5.3.18:compile -- module spring.expression [auto]
[INFO]    org.springframework.boot:spring-boot-starter-test:jar:2.6.6:test -- module spring.boot.starter.test [auto]
[INFO]    org.springframework.boot:spring-boot-test:jar:2.6.6:test -- module spring.boot.test [auto]
[INFO]    org.springframework.boot:spring-boot-test-autoconfigure:jar:2.6.6:test -- module spring.boot.test.autoconfigure [auto]
[INFO]    com.jayway.jsonpath:json-path:jar:2.6.0:test -- module json.path (auto)
[INFO]    net.minidev:json-smart:jar:2.4.8:test -- module json.smart (auto)
[INFO]    net.minidev:accessors-smart:jar:2.4.8:test -- module accessors.smart (auto)
[INFO]    org.ow2.asm:asm:jar:9.1:test -- module org.objectweb.asm
[INFO]    org.slf4j:slf4j-api:jar:1.7.36:compile -- module org.slf4j [auto]
[INFO]    jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:test -- module java.xml.bind
[INFO]    jakarta.activation:jakarta.activation-api:jar:1.2.2:test -- module jakarta.activation
[INFO]    org.assertj:assertj-core:jar:3.21.0:test -- module org.assertj.core
[INFO]    org.hamcrest:hamcrest:jar:2.2:test -- module org.hamcrest [auto]
[INFO]    org.junit.jupiter:junit-jupiter:jar:5.8.2:test -- module org.junit.jupiter
[INFO]    org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test -- module org.junit.jupiter.api
[INFO]    org.opentest4j:opentest4j:jar:1.2.0:test -- module org.opentest4j
[INFO]    org.junit.platform:junit-platform-commons:jar:1.8.2:test -- module org.junit.platform.commons
[INFO]    org.apiguardian:apiguardian-api:jar:1.1.2:test -- module org.apiguardian.api
[INFO]    org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test -- module org.junit.jupiter.params
[INFO]    org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test -- module org.junit.jupiter.engine
[INFO]    org.junit.platform:junit-platform-engine:jar:1.8.2:test -- module org.junit.platform.engine
[INFO]    org.mockito:mockito-core:jar:4.0.0:test -- module org.mockito [auto]
[INFO]    net.bytebuddy:byte-buddy:jar:1.11.22:test -- module net.bytebuddy
[INFO]    net.bytebuddy:byte-buddy-agent:jar:1.11.22:test -- module net.bytebuddy.agent
[INFO]    org.objenesis:objenesis:jar:3.2:test -- module org.objenesis [auto]
[INFO]    org.mockito:mockito-junit-jupiter:jar:4.0.0:test -- module org.mockito.junit.jupiter [auto]
[INFO]    org.skyscreamer:jsonassert:jar:1.5.0:test -- module jsonassert (auto)
[INFO]    com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test -- module android.json (auto)
[INFO]    org.springframework:spring-core:jar:5.3.18:compile -- module spring.core [auto]
[INFO]    org.springframework:spring-jcl:jar:5.3.18:compile -- module spring.jcl [auto]
[INFO]    org.springframework:spring-test:jar:5.3.18:test -- module spring.test [auto]
[INFO]    org.xmlunit:xmlunit-core:jar:2.8.4:test -- module org.xmlunit [auto]
[INFO] 
[INFO] 
[INFO] --------------------< com.example.demo0402:module2 >--------------------
[INFO] Building module2 0.0.1-SNAPSHOT                                    [3/3]
............
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Aggregator 0.0.1-SNAPSHOT:
[INFO] 
[INFO] Aggregator ......................................... SUCCESS [  0.554 s]
[INFO] module1 ............................................ SUCCESS [  0.289 s]
[INFO] module2 ............................................ SUCCESS [  0.247 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.463 s
[INFO] Finished at: 2022-04-05T09:44:06+08:00
[INFO] ------------------------------------------------------------------------

mvn dependency:tree

该命令以树的形式显示依赖。例如:

➜  aggregator git:(main) ✗ mvn dependency:tree
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Aggregator                                                         [pom]
[INFO] module1                                                            [jar]
[INFO] module2                                                            [jar]
[INFO] 
[INFO] ------------------< com.example.demo0402:aggregator >-------------------
[INFO] Building Aggregator 0.0.1-SNAPSHOT                                 [1/3]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) @ aggregator ---
[INFO] com.example.demo0402:aggregator:pom:0.0.1-SNAPSHOT
[INFO] 
[INFO] --------------------< com.example.demo0402:module1 >--------------------
[INFO] Building module1 0.0.1-SNAPSHOT                                    [2/3]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) @ module1 ---
[INFO] com.example.demo0402:module1:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.6.6:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.6.6:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.6.6:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.6.6:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.6.6:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.29:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.6.6:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.2.2:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.2:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.13.2:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.2:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.2:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.2:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.6.6:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.60:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.60:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.60:compile
[INFO] |  +- org.springframework:spring-web:jar:5.3.18:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.3.18:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.18:compile
[INFO] |     +- org.springframework:spring-aop:jar:5.3.18:compile
[INFO] |     +- org.springframework:spring-context:jar:5.3.18:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.3.18:compile
[INFO] \- org.springframework.boot:spring-boot-starter-test:jar:2.6.6:test
[INFO]    +- org.springframework.boot:spring-boot-test:jar:2.6.6:test
[INFO]    +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.6.6:test
[INFO]    +- com.jayway.jsonpath:json-path:jar:2.6.0:test
[INFO]    |  +- net.minidev:json-smart:jar:2.4.8:test
[INFO]    |  |  \- net.minidev:accessors-smart:jar:2.4.8:test
[INFO]    |  |     \- org.ow2.asm:asm:jar:9.1:test
[INFO]    |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO]    +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:test
[INFO]    |  \- jakarta.activation:jakarta.activation-api:jar:1.2.2:test
[INFO]    +- org.assertj:assertj-core:jar:3.21.0:test
[INFO]    +- org.hamcrest:hamcrest:jar:2.2:test
[INFO]    +- org.junit.jupiter:junit-jupiter:jar:5.8.2:test
[INFO]    |  +- org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[INFO]    |  |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO]    |  |  +- org.junit.platform:junit-platform-commons:jar:1.8.2:test
[INFO]    |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO]    |  +- org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test
[INFO]    |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test
[INFO]    |     \- org.junit.platform:junit-platform-engine:jar:1.8.2:test
[INFO]    +- org.mockito:mockito-core:jar:4.0.0:test
[INFO]    |  +- net.bytebuddy:byte-buddy:jar:1.11.22:test
[INFO]    |  +- net.bytebuddy:byte-buddy-agent:jar:1.11.22:test
[INFO]    |  \- org.objenesis:objenesis:jar:3.2:test
[INFO]    +- org.mockito:mockito-junit-jupiter:jar:4.0.0:test
[INFO]    +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO]    |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO]    +- org.springframework:spring-core:jar:5.3.18:compile
[INFO]    |  \- org.springframework:spring-jcl:jar:5.3.18:compile
[INFO]    +- org.springframework:spring-test:jar:5.3.18:test
[INFO]    \- org.xmlunit:xmlunit-core:jar:2.8.4:test
[INFO] 
[INFO] --------------------< com.example.demo0402:module2 >--------------------
[INFO] Building module2 0.0.1-SNAPSHOT                                    [3/3]
[INFO] --------------------------------[ jar ]---------------------------------
............
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Aggregator 0.0.1-SNAPSHOT:
[INFO] 
[INFO] Aggregator ......................................... SUCCESS [  0.569 s]
[INFO] module1 ............................................ SUCCESS [  0.111 s]
[INFO] module2 ............................................ SUCCESS [  0.024 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.098 s
[INFO] Finished at: 2022-04-05T09:48:29+08:00
[INFO] ------------------------------------------------------------------------

mvn dependency:analyze

该命令用来分析依赖。例如:

➜  aggregator git:(main) ✗ mvn dependency:analyze
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Aggregator                                                         [pom]
[INFO] module1                                                            [jar]
[INFO] module2                                                            [jar]
[INFO] 
[INFO] ------------------< com.example.demo0402:aggregator >-------------------
[INFO] Building Aggregator 0.0.1-SNAPSHOT                                 [1/3]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] >>> maven-dependency-plugin:3.2.0:analyze (default-cli) > test-compile @ aggregator >>>
[INFO] 
[INFO] <<< maven-dependency-plugin:3.2.0:analyze (default-cli) < test-compile @ aggregator <<<
[INFO] 
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:analyze (default-cli) @ aggregator ---
[INFO] Skipping pom project
[INFO] 
[INFO] --------------------< com.example.demo0402:module1 >--------------------
[INFO] Building module1 0.0.1-SNAPSHOT                                    [2/3]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] >>> maven-dependency-plugin:3.2.0:analyze (default-cli) > test-compile @ module1 >>>
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ module1 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ module1 ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ module1 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory /home/ding/Downloads/test0402/aggregator/module1/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ module1 ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] <<< maven-dependency-plugin:3.2.0:analyze (default-cli) < test-compile @ module1 <<<
[INFO] 
[INFO] 
[INFO] --- maven-dependency-plugin:3.2.0:analyze (default-cli) @ module1 ---
[WARNING] Used undeclared dependencies found:
[WARNING]    org.springframework.boot:spring-boot-autoconfigure:jar:2.6.6:compile
[WARNING]    org.springframework.boot:spring-boot:jar:2.6.6:compile
[WARNING]    org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[WARNING]    org.springframework.boot:spring-boot-test:jar:2.6.6:test
[WARNING] Unused declared dependencies found:
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:2.6.6:compile
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:2.6.6:test
[INFO] 
[INFO] --------------------< com.example.demo0402:module2 >--------------------
[INFO] Building module2 0.0.1-SNAPSHOT                                    [3/3]
[INFO] --------------------------------[ jar ]---------------------------------
............
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Aggregator 0.0.1-SNAPSHOT:
[INFO] 
[INFO] Aggregator ......................................... SUCCESS [  0.543 s]
[INFO] module1 ............................................ SUCCESS [  1.136 s]
[INFO] module2 ............................................ SUCCESS [  0.212 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.264 s
[INFO] Finished at: 2022-04-05T09:49:03+08:00
[INFO] ------------------------------------------------------------------------

结果中有非常重要的两部分:

  • Used undeclared dependencies使用了但未声明的依赖,比如模块实际上依赖于A和B,而A本身也依赖于B,则只需声明依赖A即可,B也会被隐式加入。但是这种做法显然不好,以后如果A升级了,不依赖于B了,代码就会报错。
  • Unused declared dependencies声明了但未使用的依赖。比如本例中的 spring-boot-starter-web ,虽然声明了该依赖,但在代码中并没有使用相关的功能,所以是多余的。但是对于此类依赖,也不要轻易删除,一来可能是因为将来会用,二来分析结果只包含main和test所需要的依赖,一些其它的比如运行时依赖则没考虑在内。总之要小心测试,谨慎删除。

你可能感兴趣的:(maven)