Maven中依赖冲突与循环依赖是开发过程中比较令人头疼的问题。
首先介绍下Maven中依赖管理的策略。
依赖传递:如果A依赖B,B依赖C,那么引入A,意味着B和C都会被引入。
最近依赖策略:如果一个项目依赖相同的groupId、artifactId的多个版本,那么在依赖树(mvn dependency:tree)中离项目最近的那个版本将会被使用。
具体如下:
2. 同级别的引用,若pom.xml直接引用了两个不同版本的同一个依赖,maven会使用后解析的依赖版本。
3. 若两个不同版本的同一依赖都不是直接在pom.xml下引入,而是间接引入。那么哪个依赖先被引用,就使用哪个版本。
<dependencyManagement>
用于子模块的版本一致性,可以在parent工程里统一管理所有工程的依赖版本。<exclusions>
去除多余的依赖,IDEA提供相关可视化的操作。<dependency>
,直接在当前项目中指定依赖版本。实际开发中依赖冲突的问题复杂多变,需要具体问题具体处理。除了上面三种解决方法,工程结构调整也是一个可能的选择。
正常情况下,循环依赖是很少见的,当很多个项目互相引用的时候,就可能出现循环依赖,一般根据错误信息就能解决循环依赖。
build-helper-maven-plugin
插件可以解决无法构建的问题,但是只是一个规避措施,工程的依赖关系依然是混乱的。比如A依赖B,B依赖C,C依赖A的情况。这个插件提供了一种规避措施,即临时地将工程A、B、C合并成一个中间工程,编译出临时的模块D。然后A、B、C再分别依赖临时模块D进行编译。
2. 通过重构,从根本上消除循环依赖。
3. 如果循环依赖中确实有多余的部分,可以使用<exclusions>
去除多余的依赖。(IDEA可以通过图像化界面定位循环依赖)
一般分为多个段,第一段为域,第二段为公司名称…域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。
一个Maven项目,同一个groupId同一个artifactId下,只会加载一个version。
例如:
<dependency>
<groupId>org.xiaohui</groupId>
<artifactId>maven-desc</artifactId>
<version>5.3.8</version>
</dependency>
依照这个设置,包结构最好是org.xiaohui.maven-desc
。如果有个StudentDao,那全路径就是org.xiaohui.maven-desc.dao.StudentDao
。
${user_home}/.m2/repository/
,Maven默认会先从本地仓库内寻找所需Jar包。如果本地仓库不存在,Maven才会向远程仓库请求下载,同时缓存到本地仓库。IDEA中的Maven插件功能如图:
这个图表示Maven逐次递进(执行下面的命令就会包含上面的)的打包命令。
常用的打包命令:
代码有编译、测试、运行的过程,显然有些依赖只用于测试,比如Junit;有些依赖编译用不到,只有运行的时候才能用到,比如MySQL的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,只需要的是编译期提供而已。
所以Maven支持指定依赖的scope: