2017-10-08 8 views
3

JDK 9でSPIを試しています。JDK 9では "module-info.java"を除いてすべてのサンプルが動作します。 "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()); 
    } 
} 

この2つの「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 

私はコンパイルエラーのsugestsとしてパッケージ名を変更しようとしましたが、次に "split package"の問題を導入しました。

完全にモジュール化されたJDK 9でServiceLocatorを使用するにはどうすればよいですか?出来ますか?誰かが実際の例を見たことがありますか コードもここで見ることができます:あなたが使用して変更することができhttps://github.com/RadoslawOsinski/spidemo

+3

あなたが 'eu.com.example.text.spi.TextAPIにeu.com.example.implb.textを追加することを意味すると仮定します。TextB'はTextBとして実装されます(サービスタイプではありません)。 –

+0

ありがとうございました!私はこのタイプミスに数時間を費やしてきました。それが私の問題を解決しました。 –

答えて

3

: - ドキュメント内の

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実装を中心にサンプルを提供します。