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)
现在是有趣的部分。当我执行下面的类而没有:
然后找到实现类并打印出文本。
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
您可以更改为使用:-
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)
文档中的服务提供了一个围绕实现的示例。
| 归档时间: |
|
| 查看次数: |
589 次 |
| 最近记录: |