如何在Java/Gradle中访问依赖项的依赖项?

3

我想要访问一个库,这个库实现在我实现的另一个库中。这两个库我都有所有权。例如:

Lib1 有一个特定的类,在消费者应用程序中我想要访问它,比如 Car.java:

public class Car {
    public Int wheelsCount;
}

Lib2提供了一个API,该API会返回lib1中的Car类:

gradle.build:

...
api 'com.me.lib1:1.0' //From maven central (not currently live)

import com.lib1.Car

interface MyApi {
    public Car getCar();
}

消费者 gradle.build 文件: implementation 'com.me.lib2:1.0'

MyApi api = getMyApi()
api.getCar() // Error

无法访问类'com.lib1.Car'。检查您的模块类路径以查找缺失或冲突的依赖项。

问题:有没有使用Gradle的方法可以解决这个问题?


你是指消费者的gradle.build中的lib2吗? - Alexey Romanov
无论如何,将lib1的依赖项标记为lib2的“api”应该足以使用其类型。请仔细检查它是否是“api”,而不是“implementation”,如果是,请尝试创建一个https://stackoverflow.com/help/minimal-reproducible-example。 - Alexey Romanov
1个回答

0

我不确定你在问什么。这里有一个例子,我认为大致上可以做到你所说的内容?


我们有一个Gradle项目,其中包含3个子项目:cargarageappcargarage提供库,而app是我们的应用程序。除了这些目录外,根目录只包含一个名为settings.gradle的文件,并且其内容如下:
rootProject.name = 'example'
include 'car', 'garage', 'app'

继续往下,我们有一个名为car的项目,它提供了一个接口。它的build.gradle如下所示:
plugins {
  id 'java-library'
}

除此之外,它只包含我们的接口在src/main/java/car/Car.java中:

package car;

public interface Car {
  void drive();
}

garagecar项目的消费者,提供了获取新的Car的方法。因此,我们需要像这样声明对:carapi依赖:

plugins {
  id 'java-library'
}

dependencies {
  api project(':car')
}

Garage类本身看起来像这样(在src/main/java/garage/Garage.java下):

package garage;

import car.Car;

public class Garage {
  public Car getCar() {
    return () -> { System.out.println("Hello World!"); };
  }
}

最后,我们有了一个应用程序,它只需要在 implementation 中添加对 garage 的依赖以使用它并使用 JavaExec 任务来运行它:

plugins {
  id 'java'
}

dependencies {
  implementation project(':garage')
}

task run(type: JavaExec) {
  main = 'app.Main'
  classpath = sourceSets.main.runtimeClasspath
}

实际的实现再次转到 src/main/java/app/Main.java

package app;

import garage.Garage;

public class Main {
  public static void main(String[] args) {
    Garage g = new Garage();
    g.getCar().drive();
  }
}

现在我们可以通过 gradle :app:run 来运行整个程序,这将给我们输出以下内容:
> Task :app:run
Hello World!

BUILD SUCCESSFUL in 506ms
6 actionable tasks: 1 executed, 5 up-to-date
<-------------> 0% WAITING
> IDLE

所以,正如您所看到的,除了您已经说明的事情之外,您不需要做任何特殊的事情。这是假设您正在使用类路径。如果您正在使用Java 9+模块系统,则还有一些额外的步骤,但我认为这超出了本问题的范围。


如果所有库都在同一个 Gradle 项目中,则我的示例将起作用,但当它们被导入为 JAR 文件时,它就不起作用了。那么 classpath = sourceSets.main.runtimeClasspath 这一行是做什么的? - John Sardinha
@JohnSardinha 这些东西不都在同一个gradle项目中。它们分布在3个项目中,就像我在答案中所解释的那样。无论是否在Jar中都没有任何区别。classpath = sourceSets.main.runtimeClasspath会将JavaExec任务的classpath属性设置为包括main源集及其依赖项中的所有内容。它不影响编译,只是用于运行应用程序。 - Cubic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接