1

我有问题,不知道用什么方法解决

假设我有两个服务提供者接口 (SPI)

public interface View{
    display();
}

public interface Logger{
    log(String s);
}

以及提供两种服务的服务提供商,即

public class LogView implements View, Logger{
    ...
}

问题是,当我尝试通过ServiceLoader.load(Logger.class)它获取日志服务的实例时,它与使用创建的实例不同ServiceLoader.load(View.class)。有没有办法让我可以从两个调用中获得相同的对象实例?

这个想法是,在将视图加载为 GUI 之后,我希望能够登录同一个 GUI 实例,而不是另一个。就目前而言,我被两个单独的实例困住了,所以日志确实出现了。

4

1 回答 1

2

一个解决方案已与 Java 模块一起添加,但需要注意的是它适用于显式模块,即模块信息中的服务声明,而不是META-INF/services.

然后,您可以声明一个public static T provider()方法来代替公共默认构造函数,而返回类型T必须可分配给服务类型。当这样的方法被声明时,声明的类型不需要是T它自己的实现,但如果是,它不是错误。

所以给定类声明

package somemodule;

public interface Logger{
    void log(String s);
}
package somemodule;

public interface View{
    void display();
}
package somemodule;

public class LogView implements View, Logger {
    static final LogView INSTANCE = new LogView();
    private LogView() {}

    public static LogView provider() {
        return INSTANCE;
    }

    @Override
    public void display() {
        System.out.println("display");
    }

    @Override
    public void log(String s) {
        System.out.println("log "+s);
    }

}

和一个模块声明,如

module SomeModule {
    uses somemodule.Logger;
    uses somemodule.View;

    provides somemodule.Logger with somemodule.LogView;
    provides somemodule.View with somemodule.LogView;
}

以下代码打印true

View v = ServiceLoader.load(View.class).findFirst().orElseThrow();
Logger l = ServiceLoader.load(Logger.class).findFirst().orElseThrow();
System.out.println(v == l);
于 2020-01-06T19:15:46.070 回答