Maven坐标和依赖
坐标
maven中通过groupId, artifactId, version三维坐标可以唯一标示当前项目
groupId
表示机构中的一个实际项目,一般的格式为 com.机构名称.实际项目名称
例如:com.rexluo.mvndevartifactId
一个实际项目中可能根据模块功能分为若干个maven项目,每个maven项目称为artifact(构件),命名时最好和实际项目保持一致: 实际项目名称-maven项目名称
例如:mvndev-versionchecker-pluginversion
表示当前项目的的具体版本
maven坐标中还经常用到packaging,用来标示当前项目的打包类型,例如jar, war, ejb。如果不定义,默认值为jar
依赖管理
Maven的重要作用就是通过pom.xml来管理当前maven项目对其他artifact的依赖关系
依赖的定义
<dependencies> <dependency> <groudId>group_id</groupId> <artifactId>artifact_id</artifactId> <version>version</version> </dependency> </dependencies>
依赖范围
maven中编译,测试,运行都有不同的classpath,因为依赖的构件也有不同的有效范围
compile
默认的依赖范围,对于编译,测试,运行都有效test
只对测试有效,例如junit,只是在UT和CT中需要依赖,源代码编译和运行时都不需要,不会被打包到项目的lib包中provided
编译和测试时有效,运行时无效,例如servlet-api,编译时需要,但是运行时,容器自带该jar,因此不需要打包到项目的lib包- runtime
测试和运行时有效,例如JDBC驱动,编译时只需要JDK提供的JDBC接口,运行时才需要指定具体的JDBC接口实现 - system
和provided的依赖范围一致,但是需要显式的指明依赖的artifact的路径,这种依赖不是和maven仓库解析,而是和本机绑定,很少用到 - import
后续学习再补充
依赖传递
有如下依赖关系:A -> B -> X, 那么A就会传递性依赖于X,maven中我们不需要显式的管理A对于X的依赖,maven会帮我们管理
传递依赖范围表
compile test provided runtime compile compile runtime test test test provided provided provided provided runtime runtime runtime
依赖协调
有如下两个传递依赖场景:
A -> B -> C -> X(1.0.1) / A -> D -> X(1.0.2)
A -> E -> Y(1.0.2) / A -> F -> Y(1.0.2)
对于场景1, maven根据路径优先原则,A -> D -> X路径较短,因此选择X(1.0.2)
对于场景2,由于两条路径相同,maven 2.0.9以前,会随机选取,之后的版本会按照申明优先原则,哪条路径先申明就选择哪条可选依赖
场景如下:
- A -> B (compile) -> X (compile and optional)
- A -> B (compile) -> Y (compile and optional)
由于X,Y是B的可选依赖,因此该依赖不会传递给A;
实际开发中应该尽量避免使用可选依赖
最佳实践
排除依赖:剔除不需要的传递依赖
<exclusions> <exclusion> <groupId></groupId> <artifactId></artifactId> </exclusion> </exclusions>
归类依赖:多个依赖的artifact都有相同的版本,可以通过在pom.xml中加入以下定义来归类
<properties> <springframework-version>2.5.6</springframework-version> <internal-version>master-snapshot</internal-version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-bean</artifactId> <version>${springframework-version}</version> </dependency> </dependencies>
有用的命令:
– mvn dependency:list : 列出当前项目所有的依赖artifact
– mvn dependency:tree: 列出当前项目的依赖关系
– mvn dependency:analyze: 分析当前的依赖关系
used undeclared dependencies:
使用了依赖,但是没有显式的声明,有可能是其他依赖传递进来,有潜在的问题,如果直接依赖对二级依赖的版本有变化,API可能相应变化,而导致编译,运行出错,且不易发现,应该尽量避免这种情况
unused declared dependencies:
这种情况要具体分析,可能当前项目没有直接依赖,但是其他框架对其有依赖,不能轻易删除