SPI + JDK 9 + module-info.java

Rad*_*ski 5 java spi service-locator java-9 module-info

我正在JDK 9上使用SPI进行实验。整个示例都可以在没有“ module-info.java”的JDK 9上使用。添加“ module-info.java”后,ServiceLocator找不到实现类。我很困惑,在模块化的JDK 9项目中找不到有效的SPI示例。

所以我的示例项目如下所示:

/spidemo
??? apiModule
?   ??? pom.xml
?   ??? src
?       ??? main
?           ??? java
?               ??? eu
?               ?   ??? com
?               ?       ??? example
?               ?           ??? text
?               ?               ??? spi
?               ?                   ??? TextAPI.java
?               ??? module-info.java
??? applicationB
?   ??? pom.xml
?   ??? src
?       ??? main
?           ??? java
?           ?   ??? eu
?           ?       ??? com
?           ?           ??? example
?           ?               ??? spi
?           ?                   ??? b
?           ?                       ??? application
?           ?                           ??? DemoB.java
?           ??? module-info.java
??? applicationCommon
?   ??? pom.xml
?   ??? src
?       ??? main
?           ??? java
?               ??? eu
?               ?   ??? com
?               ?       ??? example
?               ?           ??? spi
?               ?               ??? application
?               ?                   ??? TextAPIProvider.java
?               ??? module-info.java
??? implementationB
?   ??? pom.xml
?   ??? src
?       ??? main
?           ??? java
?           ?   ??? eu
?           ?       ??? com
?           ?           ??? example
?           ?               ??? implb
?           ?                   ??? text
?           ?                       ??? TextB.java
?           ??? module-info.java
?           ??? resources
?               ??? META-INF
?                   ??? services
?                       ??? eu.com.example.text.spi.TextAPI
Run Code Online (Sandbox Code Playgroud)

我介绍了界面:

package eu.com.example.text.spi;
public interface TextAPI {
    String getHelloWorldText();
}
Run Code Online (Sandbox Code Playgroud)

该接口通过以下方式实现:

package eu.com.example.implb.text;
import eu.com.example.text.spi.TextAPI;
public class TextB implements TextAPI { 
    public String getHelloWorldText() {
        return "Text from B implementation";
    }
}
Run Code Online (Sandbox Code Playgroud)

通过以下代码搜索该实现:

package eu.com.example.spi.application;
import eu.com.example.text.spi.DefaultTextAPI;
import eu.com.example.text.spi.TextAPI;
import java.util.ServiceLoader;
public class TextAPIProvider {

    public static TextAPI getProvider(String providerName) {
        ServiceLoader<TextAPI> serviceLoader = ServiceLoader.load(TextAPI.class);
        for (TextAPI provider : serviceLoader) {
            String className = provider.getClass().getName();
            if (providerName.equals(className)) {
                return provider;
            }
        }
        throw new RuntimeException(providerName + " provider is not found!");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在是有趣的部分。当我执行下面的类而没有:

  • /implementationB/src/main/java/module-info.java
  • /applicationB/src/main/java/module-info.java

然后找到实现类并打印出文本。

package eu.com.example.spi.b.application;
import eu.com.example.spi.application.TextAPIProvider;
public class DemoB {
    public static void main(String[] args) {
        System.out.println("---> " + TextAPIProvider.getProvider("eu.com.example.implb.text.TextB").getHelloWorldText());
    }
}
Run Code Online (Sandbox Code Playgroud)

引入这两个“ module-info.java”文件后,ServiceLocator找不到该实现类。/applicationB/src/main/java/module-info.java的内容:

module eu.com.example.applicationB {
    requires eu.com.example.apiModule;
    requires transitive eu.com.example.applicationCommon;
    uses eu.com.example.text.spi.TextAPI;
}
Run Code Online (Sandbox Code Playgroud)

/implementationB/src/main/java/module-info.java的内容:

module eu.com.example.implb.text {
    requires eu.com.example.apiModule;
    exports eu.com.example.implb.text;
//    provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
}
Run Code Online (Sandbox Code Playgroud)

当我取消评论时:

provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
Run Code Online (Sandbox Code Playgroud)

行然后发生编译错误:

.../implementationB/src/main/java/module-info.java:[7,74] the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
.../implementationB/src/main/java/module-info.java:[7,5] service implementation must be defined in the same module as the provides directive
Run Code Online (Sandbox Code Playgroud)

由于编译错误,我试图更改程序包名称,但是随后引入了“拆分程序包”问题。

在完全模块化的JDK 9中使用ServiceLocator应该怎么做?可能吗?有人看过工作示例吗?代码也可以在这里看到:https : //github.com/RadoslawOsinski/spidemo

Nam*_*man 5

您可以更改为使用:-

provides eu.com.example.text.spi.TextAPI with eu.com.example.implb.text.TextB; 
// you provide a service through its implementation
Run Code Online (Sandbox Code Playgroud)

代替

provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI; 
Run Code Online (Sandbox Code Playgroud)

文档中的服务提供了一个围绕实现的示例。