JPMS ServiceLoader 对我不起作用

JPMS ServiceLoader does not work for me as expected

JPMS ServiceLoader 无法正常工作。

我正在尝试提供一个 桌面程序作为可执行 jar 具有默认服务,可以由个人用户超载。用户提供他们自己的服务 class 并在命令行上将他们的名字作为参数提供。

服务:

package eu.ngong.myService;

public interface MyService {
    public String name();
    public void doSomething();
}

程序连同默认服务ifif中的第一行for 被插入用于日志记录):

package eu.ngong.myService;

import java.util.ServiceLoader;

public class ServiceUser implements MyService {
    private static MyService myService = new ServiceUser();

    public static void main(String[] args) {
        if (args.length > 0) {
            System.out.println("trying to load " + args[0] + " envirionment.");
            ServiceLoader<MyService> myServices = ServiceLoader.load(MyService.class);
            for (MyService ms : myServices) {
                System.out.println(ms.name());
                if (ms.name().equalsIgnoreCase(args[0])) {
                    myService = ms;
                }
            }
        }
        myService.doSomething();
    }

    @Override
    public void doSomething() {
        System.out.println("The default service is acting.");
    }

    @Override
    public String name() {
        return "Default";
    }
}

两者都收集在 myService.jar 中,主要 class ServiceUser 托管模块-info.java

module MyService {
    exports eu.ngong.myService;
    provides eu.ngong.myService.MyService with eu.ngong.myService.ServiceUser;
}

用户的个人jar可能

package eu.ngong.user1;
import eu.ngong.myService.MyService;
public class User1 implements MyService {

    @Override
    public String name() {
        return "User1";
    }

    @Override
    public void doSomething() {
        System.out.println("User1 is acting.");
    }

}

与模块-info.java

module User1 {
    requires MyService;
    provides eu.ngong.myService.MyService with eu.ngong.user1.User1;
}

但是,运行程序与

java -p ..\user1\user1.jar;myService.jar -jar myService.jar User1

仅导致 意外 输出

trying to load User1 environment.
The default service is acting.

虽然我预期有日志记录

trying to load User1 environment.
Default
User1
User1 is acting.

我错过了什么?

  1. 您需要申报

    uses eu.ngong.myService.MyService;
    

在您要执行服务加载代码的模块中。

  1. 尝试确保您的包装已添加 META-INF/services,以便在自动处理时通过 jar 文件正确解析模块。

由于这不适合评论,因此在此分享类似示例的发现。在通过 IntelliJ 执行时,我可以注意到该代码仅适用于 uses 声明和 user-service 模块的类路径。

此外,我尝试使用类似的命令行:

java --show-module-resolution -p base-service/target/classes:user-service/target/classes --add-modules base.service,user.service -m base.service/base.service.ServiceUser user1
root base.service file://.../base-service/target/classes/
root user.service file://.../user-service/target/classes/
user.service requires base.service file://.../base-service/target/classes/
base.service binds user.service file://.../user-service/target/classes/
...
trying to load user1 environment.
Services found : 2
User1
Default
User1 is acting.

并添加了 to seek why providing the jar's on the module path didn't work. The output was as follows and had a difference where the service module was 用户模块。

java --show-module-resolution -p base-service/target/base-service-1.0-SNAPSHOT.jar:user-service/target/user-service-1.0-SNAPSHOT.jar --add-modules base.service,user.service -m base.service/base.service.ServiceUser user1
root base.service file://...base-service/target/base-service-1.0-SNAPSHOT.jar automatic
root user.service file://...user-service/target/user-service-1.0-SNAPSHOT.jar
user.service requires base.service file://...base-service/target/base-service-1.0-SNAPSHOT.jar automatic
.....
trying to load user1 environment.
Services found : 1
User1
User1 is acting.

这也可能是您执行方式出现意外输出的原因。对我来说,Default 实现的细微差别在后者中没有得到解决。