我正在用JDK 9上的SPI進行試驗。整個示例在沒有「module-info.java」的JDK 9上運行。在添加「module-info.java」之後,ServiceLocator沒有找到實現類。我很困惑,在模塊化的JDK 9項目中我找不到工作的SPI示例。SPI + JDK 9 + module-info.java
所以我的示例項目看起來是這樣的:
/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
我已經介紹了接口:
package eu.com.example.text.spi;
public interface TextAPI {
String getHelloWorldText();
}
此接口實現:
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";
}
}
的實現是通過代碼搜索相似地:
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!");
}
}
現在是有趣的部分。當我執行下面類無:
- /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());
}
}
介紹這個兩個「module-info.java」文件實現類後不被發現的ServiceLocator。 內容/applicationB/src/main/java/module-info.java的:/implementationB/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;
}
內容:
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;
}
當我取消:
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
線則發生編譯錯誤:
.../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
我試圖將軟件包名稱更改爲編譯錯誤摘要,但後來我引入了「拆分軟件包」問題。
我該怎麼做才能在完全模塊化的JDK 9中使用ServiceLocator?可能嗎?有沒有人看過工作的例子? 代碼也可以在這裏看到:https://github.com/RadoslawOsinski/spidemo
我假設你打算增加'eu.com.example.text.spi.TextAPI和eu.com.example.implb.text。TextB「作爲TextB是實現(而不是服務類型)。 –
非常感謝!我花了幾個小時在這個錯字。這解決了我的問題。 –