Maven 依赖之最佳实践

本文探讨Maven依赖管理的最佳实践,包括排除依赖、归类依赖、优化依赖的方法及工具,如mvndependency:list、tree、analyze命令的使用,帮助开发者理解和掌握依赖管理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 简介

 在前面的博客中,可以非常详细的了解到依赖范围以及传递性依赖的含义,但在理解了主要的功能和原理之后,最需要的当然就是前人的经验总结了,即最佳实践,方便用来避免和处理很多常见的问题。

2 排除依赖

 传递性依赖会隐式的引入很多依赖,这极大的简化了项目依赖的管理,但有些场景也会有问题。例如,当前项目有一个第三方依赖,由于某些原因,依赖了另外一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖 。而SNAPSHOT依赖的不稳定性会直接影响到当前的项目,这时候就需要排除掉该SNAPSHOT,并且在当前项目中声明某个该类库的的正式发布的版本。还有一种情形就是,你可能也想要替换某个传递性依赖。
在这里插入图片描述
 上述的图片中,项目A依赖于项目B,但由于某些原因,不想引入传递性依赖C,而是自己显式的声明对于项目C 1.1.0版本的依赖。解析逻辑图如下:
在这里插入图片描述

3 归类依赖

 如果我们项目中用到很多关于Spring Framework的依赖,它们分别是org.springframework:spring-core:2.5.6, org.springframework:spring-beans:2.5.6,org.springframework:spring-context:2.5.6,它们都是来自同一项目的不同模块。因此,所有这些依赖的版本都是相同的,而且可以预见,如果将来需要升级Spring Framework,这些依赖的版本会一起升级。因此,我们应该在一个唯一的地方定义版本,并且在dependency声明引用这一版本,这一在Spring Framework升级的时候只需要修改一处即可。如果我们项目中用到很多关于Spring Framework的依赖,它们分别是org.springframework:spring-core:2.5.6, org.springframework:spring-beans:2.5.6,org.springframework:spring-context:2.5.6,它们都是来自同一项目的不同模块。因此,所有这些依赖的版本都是相同的,而且可以预见,如果将来需要升级Spring Framework,这些依赖的版本会一起升级。因此,我们应该在一个唯一的地方定义版本,并且在dependency声明引用这一版本,这一在Spring Framework升级的时候只需要修改一处即可。
 使用常量不仅让代码变得更加简洁,更重要的是可以避免重复,在需要更改PI的值的时候,只需要修改一处,降低了错误发生的概率。

<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 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.juvenxu.mvnbook.account</groupId>
    <artifactId>account-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Account Parent</name>
    <modules>
        <module>account-email</module>
        <module>account-persist</module>
        <module>account-captcha</module>
        <module>account-service</module>
        <module>account-web</module>
    </modules>
    <properties>
        <springframework.version>2.5.6</springframework.version>
        <junit.version>4.7</junit.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${springframework.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

这里使用了Maven属性,首先使用properties元素定义Maven属性,

   <properties>
        <springframework.version>2.5.6</springframework.version>
        <junit.version>4.7</junit.version>
    </properties>

该例中定义了springframework.version的子元素。有了这个属性定义之后,Maven运行的时候会将POM中的所有的${springframework.version}替换为实际值2.5.6,这和Java中庸PI来替换3.14是同样的道理。

4 优化依赖

 在软件开发的过程中,程序员会通过重构等方式不断的优化自己的代码,使其变得更简洁、更灵活。同理,程序员应该能够对Maven项目的依赖了然于胸,并对其进行优化,如去除多余的依赖,显式的声明某些必要的依赖。
Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖,也能进行调节,以确保任何一个构件只有唯一的一个版本在依赖中存在。在这些工作之后,最后得到的那些依赖被称为已解析依赖(Resolved Dependency)。

4.1 mvn dependency:list

mvn dependency:list

该命令可以用来查看当前项目的已解析依赖

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>mvn dependency:list
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.juven.mvnbook.account:account-email:
jar:1.0.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 51, colum
n 12
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-resources-plugin is missing. @ line 59, colu
mn 12
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] --------------< com.juven.mvnbook.account:account-email >---------------
[INFO] Building Account Email 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ account-email ---
[INFO]
[INFO] The following files have been resolved:
[INFO]    org.springframework:spring-beans:jar:2.5.6:compile
[INFO]    javax.mail:mail:jar:1.4.1:compile
[INFO]    javax.activation:activation:jar:1.1:compile
[INFO]    commons-logging:commons-logging:jar:1.1.1:compile
[INFO]    org.slf4j:slf4j-api:jar:1.3.1:test
[INFO]    org.springframework:spring-context-support:jar:2.5.6:compile
[INFO]    aopalliance:aopalliance:jar:1.0:compile
[INFO]    junit:junit:jar:4.7:test
[INFO]    com.icegreen:greenmail:jar:1.3.1b:test
[INFO]    org.springframework:spring-core:jar:2.5.6:compile
[INFO]    org.springframework:spring-context:jar:2.5.6:compile
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.295 s
[INFO] Finished at: 2019-06-08T16:09:24+08:00
[INFO] ------------------------------------------------------------------------

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>

从输出可以看到,已解析的依赖以列表的形式展示在终端上。并且每个依赖的范围也被打印出来。
在这个基础上,可以进一步了解项目的依赖层级。将直接在当前项目POM声明的依赖定义为顶层依赖,而这些顶层依赖的依赖为第二层依赖,以此有第三,第四级依赖。当这些依赖经过Maven解析后,就会构成一个依赖树,通过这棵依赖树就可以看到某个依赖是由那条传递路径引入的。

4.2 mvn dependency:tree

mvn dependency:tree

查看当前项目的依赖树

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>mvn dependency:tree
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.juven.mvnbook.account:account-email:
jar:1.0.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 51, colum
n 12
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-resources-plugin is missing. @ line 59, colu
mn 12
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] --------------< com.juven.mvnbook.account:account-email >---------------
[INFO] Building Account Email 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ account-email ---
[INFO] com.juven.mvnbook.account:account-email:jar:1.0.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:2.5.6:compile
[INFO] |  \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] +- org.springframework:spring-beans:jar:2.5.6:compile
[INFO] +- org.springframework:spring-context:jar:2.5.6:compile
[INFO] |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] +- org.springframework:spring-context-support:jar:2.5.6:compile
[INFO] +- javax.mail:mail:jar:1.4.1:compile
[INFO] |  \- javax.activation:activation:jar:1.1:compile
[INFO] +- junit:junit:jar:4.7:test
[INFO] \- com.icegreen:greenmail:jar:1.3.1b:test
[INFO]    \- org.slf4j:slf4j-api:jar:1.3.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.565 s
[INFO] Finished at: 2019-06-08T16:17:42+08:00
[INFO] ------------------------------------------------------------------------

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>

由上图可以看出依赖树在终端打印的形式。

4.3 IDEA查看依赖树

现在流行的Java开发IDE,诸如Eclipse和IDEA对于Maven都有很好的集成,例如查看项目依赖,在IDEA中打开POM文件中右击鼠标选择Diagrams->然后选择Show Dependencies,或者使用快捷键

Ctrl + Shift + Alt + U

在这里插入图片描述
同样查看以有向图的形式展示项目的依赖树,显然这更具有可读性。

4.4 mvn dependency:analyze

可以将POM文件中的Spring-context这一依赖删除,然后构建项目,会发现编译、测试和打包都不会有任何问题。通过分析依赖树可以看到spring-context是spring-context-support的依赖,因此会得以传递到项目的classpath中。

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>mvn dependency:analyze
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.juven.mvnbook.account:account-email:
jar:1.0.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 46, colum
n 12
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-resources-plugin is missing. @ line 54, colu
mn 12
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] --------------< com.juven.mvnbook.account:account-email >---------------
[INFO] Building Account Email 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> maven-dependency-plugin:2.8:analyze (default-cli) > test-compile @ account-email >>>
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ account-email ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ account-email ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ account-email ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ account-email ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< maven-dependency-plugin:2.8:analyze (default-cli) < test-compile @ account-email <<<
[INFO]
[INFO]
[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ account-email ---
[WARNING] Used undeclared dependencies found:
[WARNING]    org.springframework:spring-context:jar:2.5.6:compile
[WARNING] Unused declared dependencies found:
[WARNING]    org.springframework:spring-core:jar:2.5.6:compile
[WARNING]    org.springframework:spring-beans:jar:2.5.6:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.148 s
[INFO] Finished at: 2019-06-08T16:27:26+08:00
[INFO] ------------------------------------------------------------------------

D:\BaiduNetdiskDownload\Maven实战源码\ch-5\account-email>

 较为重要的为Used undeclared dependencies,意指iangmu中使用到,但是没有显式声明的依赖,这里是spring-context。这种依赖意味着潜在的风险,当前项目直接在使用它们,例如有很多的Java import语句,而这种依赖是通过直接依赖传递进来的,当升级直接依赖的时候,相关传递性依赖的版本也可能发生变化,这种变化不易察觉,但是有可能导致项目出错。结论就是:显式的声明任何项目中直接用到的依赖
 另一个比较重要的部分是Unused declared dependencies,意指项目中未使用的但是显示声明的依赖,这里有spring-core和spring-beans。对于这类依赖,我们不应该简单的直接删除其声明,而是应该仔细分析。由于dependency:analyze只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它发现不了。spring-core和spring-beans是运行Spring Framework项目必要的类库,因此不能删除。

5总结

 本文档主要是阐述了依赖相关的最佳实践。理解排除依赖的应用场景,以及熟练的使用优化依赖mvn dependency的三个命令,list、tree、analyze的使用。

6 参考

Maven 依赖详细理解

																20196816:55:33于马塍路36号端午节第二天
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值