SPI + JDK 9 + 模块-info.java
SPI + JDK 9 + module-info.java
我正在 JDK 9 上试验 SPI。整个示例在没有 "module-info.java" 的 JDK 9 上运行。添加 "module-info.java" 后,ServiceLocator 未找到实施 class。我很困惑,我无法在模块化 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
我已经介绍了界面:
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!");
}
}
现在是有趣的部分。当我在下面执行 class 时没有:
- /implementationB/src/main/java/module-info.java
- /applicationB/src/main/java/module-info.java
然后找到实现 class 并打印出文本。
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 未找到实现 class。
/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;
}
/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;
}
当我取消注释时:
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
我曾尝试根据编译错误提示更改包名称,但随后引入了 "split package" 问题。
如何在完全模块化的 JDK9 中使用 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
而不是
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
Services 文档中提供了围绕实现的示例。
一个模块可以通过特定类型的服务提供商来指定它提供的服务。它是使用 provides
和 with
关键字声明的。
语法:提供 serviceType with implementationTypes;
(可以指定多个实现类型作为逗号分隔列表)
因此在您的模块中 eu.com.example.implb.text
应该添加以下语句。
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
注意:provides
不等于 exports
。因此,任何其他需要 eu.com.example.implb.text
的模块如果不导出,将无法访问 eu.com.example.implb.text.TextB
。
我正在 JDK 9 上试验 SPI。整个示例在没有 "module-info.java" 的 JDK 9 上运行。添加 "module-info.java" 后,ServiceLocator 未找到实施 class。我很困惑,我无法在模块化 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
我已经介绍了界面:
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!");
}
}
现在是有趣的部分。当我在下面执行 class 时没有:
- /implementationB/src/main/java/module-info.java
- /applicationB/src/main/java/module-info.java
然后找到实现 class 并打印出文本。
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 未找到实现 class。 /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;
}
/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;
}
当我取消注释时:
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
我曾尝试根据编译错误提示更改包名称,但随后引入了 "split package" 问题。
如何在完全模块化的 JDK9 中使用 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
而不是
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
Services 文档中提供了围绕实现的示例。
一个模块可以通过特定类型的服务提供商来指定它提供的服务。它是使用 provides
和 with
关键字声明的。
语法:提供 serviceType with implementationTypes;
(可以指定多个实现类型作为逗号分隔列表)
因此在您的模块中 eu.com.example.implb.text
应该添加以下语句。
provides eu.com.example.implb.text.TextB with eu.com.example.text.spi.TextAPI;
注意:provides
不等于 exports
。因此,任何其他需要 eu.com.example.implb.text
的模块如果不导出,将无法访问 eu.com.example.implb.text.TextB
。