在我的项目中有一个实现接口的类。接口来自依赖。我有另一个依赖项,它本身依赖于一个jar,它也包含相同的接口,除了一个有更多方法的版本;包含相同package-interface的两个jar不具有相同的groupId或artifactId 编译失败,因为编译器抱怨我的项目中的类没有实现所有方法。我意识到这是因为编译器从错误的jar中获取接口引用。我的问题是,为什么maven使用传递依赖的接口而不是我在项目POM中明确提到的jar中的接口?我可以看到使用的jar出现在定义的前面(所以我也想象在类路径中),但我认为在这些情况下,maven通过使用来自依赖关系的碰撞类/接口与最短路径
来解决它这是依赖树的一部分。 请注意,这是grepped 但仍然可以看到javax.servlet:servlet-api
(实际使用的那个)在树中比tomcat:servlet
(应该使用的那个)更深
[builder@ca-rd-build11 proj]$ mvn dependency:tree | grep servlet
[INFO] | +- javax.servlet:servlet-api:jar:2.4:compile
[INFO] +- tomcat:servlet:jar:4.0.6:compile
我正在使用maven 3.0.4
答案 0 :(得分:18)
为什么maven使用来自传递依赖的接口 而不是我在明确提到的jar中的那个 项目POM?
因为,对于Maven来说,这两个人彼此无关。 Maven不知道类名或包名,Maven只知道groupId和artifactId。由于那些不一样,maven没有任何理由忽略传递依赖。
如果我是正确的,Maven会按照定义的顺序将依赖项放在类路径上,即依赖项a
的传递依赖项出现在依赖项b
之前。
答案 1 :(得分:5)
当您声明对其他jar文件的依赖时,您可以告诉它排除对冲突的jar文件的传递依赖:
<dependency>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>othergroup</groupId>
<artifactId>ArtifactToExclude</artifactId>
</exclusion>
</exclusions>
</dependency>
答案 2 :(得分:1)
为将来的访问者(由于标题是通用的):
在Maven中,您有两类依赖项:
<dependencies>
根据官方Maven documentation,当遇到多个版本作为依赖项时,将应用以下中介:
Maven选择“最近的定义” 。也就是说,它使用依赖关系树中最接近您的项目的版本。您始终可以通过在项目的POM中明确声明版本来保证版本。请注意,如果两个依赖关系版本在依赖关系树中的深度相同,则第一个声明将获胜。
示例:如果将A,B和C的依赖项定义为A-> B-> C-> D 2.0和A-> E-> D 1.0,则D 1.0将为在构建A时使用它,因为从A到D到E的路径较短。您可以在A中向D 2.0显式添加一个依赖项,以强制使用D 2.0。
在上面的示例中,A是实际项目,B和E是在其 pom.xml 文件中定义的外部依赖项,而C和D是可传递依赖项。