Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java/maven如何在运行时解决依赖冲突_Java_Maven - Fatal编程技术网

java/maven如何在运行时解决依赖冲突

java/maven如何在运行时解决依赖冲突,java,maven,Java,Maven,对不起,我的新手问题 假设我有一个包a,它在它的maven文件中声明了B,C作为它的依赖项。B、 C使用两个不同版本的log4j进行日志记录。我有几个问题: 如果我使用maven,并将B、C声明为A的依赖项。当maven从mavencentral repo中引入B、C的工件(.jar)时。B、C jar文件是否包含log4j类文件,或者只包含它们自己的编译文件(B、C自己的源代码,而不是依赖项) 如果我理解正确的话,当构建发生时,最终构建中只有一个log4j类文件(即使B、C使用不同版本的log

对不起,我的新手问题

假设我有一个包a,它在它的maven文件中声明了B,C作为它的依赖项。B、 C使用两个不同版本的log4j进行日志记录。我有几个问题:

  • 如果我使用maven,并将B、C声明为A的依赖项。当maven从mavencentral repo中引入B、C的工件(.jar)时。B、C jar文件是否包含log4j类文件,或者只包含它们自己的编译文件(B、C自己的源代码,而不是依赖项)
  • 如果我理解正确的话,当构建发生时,最终构建中只有一个log4j类文件(即使B、C使用不同版本的log4j)。在这里选择哪个版本的log4j进行构建?这是否意味着我也需要将log4j声明为一个依赖项(在A的maven构建文件中),并且该版本将被选择为要构建的版本
  • B、 C可能使用完全不同的log4j版本。可能会有完全不同的API。它应该在运行时引起问题吗?但事实上,这是非常罕见的?为什么会这样 谢谢

  • 它们应该只包含自己的类。而不是它们依赖的类。您可以打开jar文件,自己查看。Jar文件只是zip文件
  • Maven将通过选择最接近依赖关系树根的版本来解决冲突。如果两个版本在依赖关系树中的深度相同,则会拾取第一个版本(IIRC)。如果A本身依赖于log4j,或者如果您希望在运行时使用特定的版本,则应将log4j指定为A的直接依赖项,并使用所需的版本。或者至少在生成的dependencyManagement部分中指定它
  • 因为像Log4J这样流行的库都努力拥有一个非常稳定的API,因此不会破坏针对库的旧版本编译的代码
  • 人工制品通常不包含其依赖项(但也有打包选项)
  • Maven将使用一些规则(我不记得太详细)只确定一个版本。如果出于某种原因必须重写此项,则可以将依赖项管理部分放入POM中
  • 是的,这会引起问题。只有在更改公共API时小心,才能避免这些问题
  • jar文件通常不包含它们的依赖项。有一种方法叫做胖罐子。但我们假设您使用的是常规的jar依赖项。jar将只在自己的pom.xml中声明它们的依赖项。因此,对于您的示例,B和C将只包含它们自己编译的源代码

  • 这实际上取决于你如何打包文件。通常,如果您只生成一个简单的jar,它将不包含依赖项,并且运行程序负责提供正确的依赖项。例如,在发生战争的情况下,maven将抛出所有依赖项。前面提到的另一种方法是胖罐子。一种更常见的方法是压缩所有依赖项并分别提供它们

  • 我不知道为什么您以前没有遇到过冲突,但我不记得log4j与许多其他库有过冲突。作为库维护人员,处理此类冲突的一种方法是在进行不向后兼容的更改时,更改包名,这样用户就可以在类路径中安全地拥有多个版本(无论如何都应该避免)

  • Maven有一种避免此类冲突的方法,它将优先考虑最近定义的依赖版本。例如,如果在a中声明了版本a,在b中声明了版本b,则有效版本将是a

    此外,还有一些其他机制,如依赖关系管理。你可以看看这里:

    此主题非常严重,可能会导致许多难以检测的生产错误。希望这有助于

  • 如果将log4j指定为B和C的依赖项,并且您不使用创建uber jar/fat jar的特殊插件,那么B和C都不会包含log4j类文件

  • 一个具有相同坐标的依赖项(groupId、artifactId)。正如这里已经提到的,版本通常是通过到根的最短路径来选择的。因此,如果您想使用特定的log4j版本,只需在pom中指定即可

  • 如果以标准方式使用log4j,即仅指定配置文件,两个版本(log4j和log4j2)通常可以共存,因为它们使用不同的包和不同的配置文件。只需查看log4j的迁移站点:


  • Maven假设可以始终使用较新版本的工件,而不是较旧版本的工件。如果没有,您需要开始在依赖项中使用exclude。反例:google guava,其中较新的版本删除了旧的功能。guava违反了现有的任何版本编号模式。它们只按自己喜欢的方式玩。要么你买要么不买。。。