"检测到所需的基于文件名的自动模块"是什么.警告意味着?

Dmi*_*kiy 14 java maven-3 maven maven-compiler-plugin java-9

在我的多模块项目中,我module-info.java只创建了几个模块.在编译期间maven-compiler-plugin:3.7.0我得到下一个警告:

[警告]*检测到必需的基于文件名的自动模块.请不要将此项目发布到公共工件库!*

这是什么意思?是因为我只有几个模块,module-info.java而不是整个项目?

Nic*_*lai 15

自动模块回顾

显式模块(即带有a module-info.java的模块)只能访问它所需的模块代码(暂时忽略隐含的可读性).如果所有依赖关系都是模块化的,那就太棒了,但如果不是这样的话呢?如何引用非模块化的JAR?

自动模块就是答案:任何以模块路径结束的JAR都会变成一个模块.如果JAR不包含模块声明,则模块系统将创建具有以下属性的自动模块:

  • 推断名称(这是重要的一点)
  • 读取所有其他模块
  • 导出所有包裹

Maven依赖于该机制,一旦您创建了module-info.jar它,它就会将所有依赖项放在模块路径上.

自动名称

有两种方法可以推断自动模块的名称:

  • 进入清单
  • 从JAR文件名猜测

在第一种情况下,名称是由维护者故意挑选的,因此可以假设它是稳定的(例如,当项目模块化时它不会改变).第二个在整个生态系统中显然是不稳定的 - 并非所有项目设置都会导致其依赖项的文件名完全相同.

这是什么意思?

警告的原因是您的某些依赖项是自动模块,并且未在清单中定义其未来的模块名称.相反,它们的名称来自文件名,这使它们不稳定

名字稳定

那么为什么不稳定的名字会出现问题呢?假设您的库已发布,requires guava并且我的框架已发布requires com.google.guava.现在有人在我的框架中使用你的库,突然他们需要在模块路径上使用模块guavacom.google.guava.这个问题没有无痛的解决办法,所以需要加以防范!

怎么样?例如,通过阻止开发人员发布依赖于基于文件名的自动模块的工件.

  • “没有一个无痛的解决方案可以解决这个问题”……嗯,实际上存在一个无痛的解决方案。不需要通过身份而是功能来要求模块,例如它们导出的软件包。但是,当然,该解决方案被拒绝了,不可避免地导致了您所描述的确切问题。如果有人警告过他们…… (3认同)
  • 需要包而不是模块使描述符像在类开始时的导入一样嘈杂且无用。很有可能,它们甚至会自动生成,在没有价值的基础上增加了一个额外的构建步骤。我很高兴依赖项是模块而不是包。 (2认同)
  • OSGi已经这样做了18年,是的,我们在运行时工件中生成了它们。在构建时,我们当然会使用工件依赖项。有趣的是,您说这不能解决您所描述的确切问题时没有任何价值。 (2认同)
  • @NeilBartlett 和 OSGi 的采用,进展如何? (2认同)

Nam*_*man 6

[警告] * 检测到必需的基于文件名的自动模块。请不要将此项目发布到公共工件存储库!*

这是因为我只有几个带有 module-info.java 的模块而不是整个项目吗?

不,这不是因为列出了几个模块,而是由模块图中找到的所有自动模块module-info.java生成的。maven-compiler-plugin


这是什么意思?

坚持不发布当前项目可能是因为自动模块预计将由其所有者转换为命名或显式模块,然后发布到存储库,这也可能导致其模块名称发生更改。另外需要注意的是,根据 Maven ~> Java+9+-+Jigsaw的进度文档,他们还没有完全准备好兼容 JDK9 的插件版本。


只是为此类用例描绘一个示例。想想这些线——

  • 我发布了一个神器com-foo-bar:1.0.0-SNAPSHOT:jar
  • 我的另一个项目com-xyz:1.0.0依赖于它。
  • 最终你的项目依赖于com-foo-bar传递com-xyz
  • 您计划模块化您的代码并利用类似的东西

    module your.module {
        requires com.foo.bar;
        requires com.xyz;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    (需要在模块声明中单独指定传递依赖)

  • 一切都工作正常,但直到我决定模块化我的库。
  • 现在,我做的第一件事就是命名我的模块
  • 我做了一些很棒的事情来明确地表达我的努力,如下所示:-

    module modular.com.foo.bar {}
    
    Run Code Online (Sandbox Code Playgroud)
  • 我最终破坏了任何依赖库的代码,最终以模块化的方式破坏了任何依赖于你的库的代码。

注意:我同意不在生产中练习使用快照,但在某些情况下,您最终可能会依赖仍处于开发阶段的工件。


编辑:来自@khmarbaise的评论

据了解,人们希望发布到人工制品,但如果他们不知道后果,你将来就会被打败。

Maven 想要明确表示,这种情况下的警告非常严重,这可能是一个失败,但这将是一个糟糕的用户体验。

处理这个问题的理想方法是,库所有者计划将他们的工件迁移到 JDK9,并且自下而上遍历树,在这种情况下,命名/显式模块将是唯一流行的方面,而不需要自动模块名称和这样的警告。