我已经创建了一个简单的仓库来测试这个问题:
https://github.com/fvigotti/gradle-implementation-error
5.4.1版,但在升级之前也已对以前的版本进行了测试。
实现不应泄漏“实现库”
一切都泄漏了。
我创建了一个空的临时示例项目来演示这一点。 https://github.com/fvigotti/gradle-implementation-error
gradle clean build publishToMavenLocal
然后转到另一个项目并导入:
implementation "net.me:library-sample:1.0-SNAPSHOT"
这不应该被暴露:
import org.apache.commons.codec.Decoder
就是这样!
我正在测试在github上发现的更多资源,似乎几乎每个人都在使用
from components.java
不用担心实现依赖性泄漏……我确定我在这里遗漏了一些东西。
谢谢你, 弗朗切斯科
以下是问题的视频: https://vimeo.com/334392418
答案 0 :(得分:0)
您在your bug report to IntelliJ中说:“ 我很惊讶没有人浮出水面”。可能它尚未浮出水面的原因可能是因为您在现实世界中遇到的不是问题。
我认为真正的问题可能是了解Java中类加载的臭名昭著的本质。
类加载必须能够在系统级别 和 上都可以工作。 Class.forName(String)
实际上是在系统级别上工作。但是,通过调用 Class
来从应用程序级别驱动系统级别。
Gradle的api /实现约束仅适用于应用程序级别。不在系统级别。在Gradle构建运行的上下文之外,Gradle无法对Java类加载系统本身的设计运行方式施加约束。
这就像我不应该能够从文字处理器应用程序访问计算机的CPU指令寄存器。但这并不意味着应该禁止操作系统以某种方式与CPU接口。
在您的情况下,您的 net.me.consumer.Main
类是“ 文字处理器”。 org.apache.commons.csv.CSVFormat
和 org.apache.commons.codec.Decoder
类似于CPU中的指令。并且 java.lang.Class
类似于操作系统。
您不能直接从文字处理器访问CPU。但是,您可以在字处理器中执行使OS与CPU交互的操作。您正在使用 Class.forName(decoderClazzName)
做类似的事情。
您的项目演示的相同“ 泄漏”也可以在Eclipse中复制。以及在Visual Studio Code中。实际上,我可以将它添加到您的消费者项目的 Main
和 MainTest
类中:
org.apache.commons.codec.Decoder decoder = new Decoder() {
@Override
public Object decode(Object source) throws DecoderException {
// TODO Auto-generated method stub
return null;
}
};
Eclipse不仅允许它,它还会自动为我创建它。加上它添加了必要的导入语句,甚至我都没有要求。并且非常轻松愉快地编译它,没有问题也没有抱怨。即使您的消费者的 commons-codec
中定义的 build.gradle
不存在依赖性。
尽管我没有在NetBeans中尝试过它,但我怀疑您在该版本或任何其他Java IDE中会得到相同的结果。
向IntelliJ提交错误的方式,还必须向每个Java IDE,每个基于Java的应用程序服务器,每个基于JVM的编译器等提交错误。
我认为期望Java生态系统中的每个软件供应商都遵守由一个依赖管理工具定义的约束是不合理的。不管他们想怎样,它们都是