环境
- 操作系统:
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
其中, groupId
、 artifactId
、 version
是必需的, packaging
是可选的(默认值为 jar
),而 classifier
是不能直接定义的。
问题
在POM中,我们可以定义依赖关系,例如:
............
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
............
<dependencies>
............
被依赖的artifact(本例中是 spring-boot-starter-web
),显然也需要 groupId
、 artifactId
、 version
来唯一标识,然而,这里只有 groupId
和 artifactId
,并没有 version
。这是怎么回事呢?
带着这个问题,我们来看一下Maven的依赖(dependency)。
聚合和继承
一个项目(project)的开发,通常采用“模块化开发”的方式,项目是由多个模块(module)所组成,模块秉承“高内聚,低耦合”的原则。例如开发团队分为多个小组,每组只专注于各自所负责的模块的开发和调试。但项目作为一个整体,需要在总体上进行管理和构建。
Maven提供了 聚合
和 继承
这两个概念:
- 聚合:把各个模块聚合在一起构建;
- 继承:抽取各个模块相同的依赖和插件等配置,以简化配置,方便维护;
聚合
聚合比较简单,就是把多个模块在一起构建。例如,我们有 module1
和 module2
两个模块。为了把它们聚合在一起,我们再创建一个额外的 aggregator
模块。该模块本身作为一个Maven项目,有自己的pom文件,但是它不涉及项目的具体业务逻辑,所以没有src等目录。
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>com.example.demo0402</groupId>
<artifactId>aggregator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Aggregator</name>
<modules>
<module>module1</module>
<module>module2</module>
</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
。
继承
module1
和 module2
模块有很多相同的配置,比如 groupId
和 version
,此外还有 spring-boot-starter-web
等三方依赖包也一样。重复的配置显然增加了维护成本,并带来潜在的不一致风险。
Maven提供了继承机制,来抽取重复的配置。这有点类似于面向对象的父子类关系,在父POM中定义一些配置以供子POM来继承。
“父POM”与“聚合POM”有些相似之处:
- POM的
packaging
必须为pom
; - 不需要src目录;
在 aggregator
目录下创建一个 parent
目录,然后在 parent
目录里创建 pom.xml
文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>com.example.demo0402</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Parent</name>
</project>
有了父模块, module1
和 module2
还必须显式的声明继承关系。
以 module1
为例,在其pom.xml文件中添加如下内容:
<parent>
<groupId>com.example.demo0402</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
module1
可以删除自己的 groupId
和 version
设置,默认会从父模块继承。这样,就可以确保各个模块始终保持相同的 groupId
和 version
。
注: relativePath
的默认值是 ../pom.xml
,即上一级目录。
接下来,我们来把dependency抽取到父模块。
若直接把子模块中公共的dependency配置移到父模块,固然OK,不过这种做法存在一个问题,如果以后再有新的子模块(如 module3
),而新的子模块并不需要这些dependency,这就难办了。
所以Maven提供了 dependencyManagement
元素。
- 在父模块中通过
dependencyManagement
元素声明dependency; - 在子模块中通过
dependency
元素引用所需的dependency;
在父模块POM中添加如下内容:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
</dependencies>
</dependencyManagement>
在子模块POM的 dependencies
中添加如下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
我们看到,子模块的dependency只需指明 groupId
和 artifactId
,而无需指定 version
。这是因为完整的dependency信息是在父模块的 dependencyManagement
定义的,所以子模块只需通过 groupId
和 artifactId
来引用即可。
这种做法的好处是:
- 统一性:所有dependency都由父模块统一定义,确保子模块使用的dependency版本一致;
- 灵活性:子模块只需引用自己所需的dependency;
有一种特殊的依赖范围( scope
),叫做 import
。这种依赖通常指向一个POM,作用是将其 dependencyManagement
配置导入到当前的POM中。例如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example.demo0402</groupId>
<artifactId>xxx</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.example.demo0402</groupId>
<artifactId>yyy</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
............
</dependencies>
</dependencyManagement>
常见做法是把依赖根据类型不同,生成多个POM(如上例中的 xxx
、 yyy
等),然后在父模块中将其一一导入,以便“分而治之”。
聚合与继承的关系
共同点
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所需要的依赖,一些其它的比如运行时依赖则没考虑在内。总之要小心测试,谨慎删除。