我试图弄清楚在构建依赖关系时api和实现配置之间的区别。
在文档中,它说实现有更好的构建时间,但是,在一个类似的问题中看到这个评论,我想知道这是否是真的。
因为我不是Gradle的专家,我希望有人能帮助我。我已经阅读了文档,但我想知道一个简单易懂的解释。
我试图弄清楚在构建依赖关系时api和实现配置之间的区别。
在文档中,它说实现有更好的构建时间,但是,在一个类似的问题中看到这个评论,我想知道这是否是真的。
因为我不是Gradle的专家,我希望有人能帮助我。我已经阅读了文档,但我想知道一个简单易懂的解释。
当前回答
来自gradle文档:
让我们看一下基于jvm的项目的一个非常简单的构建脚本。
plugins {
id 'java-library'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.hibernate:hibernate-core:3.6.7.Final'
api 'com.google.guava:guava:23.0'
testImplementation 'junit:junit:4.+'
}
实现 编译项目的生产源代码所需的依赖项,这些依赖项不是项目公开的API的一部分。例如,该项目使用Hibernate进行内部持久层实现。 api 编译项目生产源代码所需的依赖项,这些依赖项是项目公开的API的一部分。例如,该项目使用了Guava,并在方法签名中公开了带有Guava类的公共接口。
其他回答
假设你有一个应用模块,它使用lib1作为库,lib1使用lib2作为库。就像这样:app -> lib1 -> lib2。
现在当在lib1中使用api lib2时,当在app模块中使用api lib1或实现lib1时,app可以看到lib2代码。
但是当在lib1中使用实现lib2时,应用程序无法看到lib2代码。
@matpag和@dev-bmax的回答足够清楚,让人们理解实现和api之间的不同用法。我只是想从另一个角度做一个额外的解释,希望对有同样问题的人有所帮助。
我创建了两个项目进行测试:
项目A作为一个名为“frameworks-web-gradle-plugin”的java库项目依赖于“org.springframework.boot:spring-boot-gradle-plugin:1.5.20.RELEASE” 项目B依赖于项目A的实现'com.example.frameworks.gradle:frameworks-web-gradle-plugin:0.0.1-SNAPSHOT'
上面描述的依赖层次结构如下:
[project-b] -> [project-a] -> [spring-boot-gradle-plugin]
然后我测试了以下场景:
Make project A depends on 'org.springframework.boot:spring-boot-gradle-plugin:1.5.20.RELEASE' by implementation . Run gradle dependencies command in a terminal in poject B root dir,with following screenshot of output we can see that 'spring-boot-gradle-plugin' appears in runtimeClasspath dependencies tree, but not in compileClasspath's, I think that's exactly why we can't make use of library that declared using implementation, it just won't through compilation. Make project A depends on 'org.springframework.boot:spring-boot-gradle-plugin:1.5.20.RELEASE' by api Run gradle dependencies command in a terminal in poject B root dir again. Now 'spring-boot-gradle-plugin' appears both in compileClasspath and runtimeClasspath dependencies tree.
我注意到一个显著的区别是,在生产者/库项目中以实现方式声明的依赖项不会出现在消费者项目的compileClasspath中,因此我们不能在消费者项目中使用相应的库。
文档中有很好的解释
api配置应该用于声明依赖关系 由库API导出,而实现配置 应用于声明依赖项,这些依赖项是 组件。
我喜欢把api依赖看作是公共的(其他模块可以看到),而实现依赖则是私有的(只有这个模块可以看到)。
注意,与公共/私有变量和方法不同,api/实现依赖关系不是由运行时强制执行的。这只是一个构建时优化,它允许Gradle知道当某个依赖项更改API时需要重新编译哪些模块。
来自gradle文档:
让我们看一下基于jvm的项目的一个非常简单的构建脚本。
plugins {
id 'java-library'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.hibernate:hibernate-core:3.6.7.Final'
api 'com.google.guava:guava:23.0'
testImplementation 'junit:junit:4.+'
}
实现 编译项目的生产源代码所需的依赖项,这些依赖项不是项目公开的API的一部分。例如,该项目使用Hibernate进行内部持久层实现。 api 编译项目生产源代码所需的依赖项,这些依赖项是项目公开的API的一部分。例如,该项目使用了Guava,并在方法签名中公开了带有Guava类的公共接口。