2017-10-08 11 views
3

JDK 9에서 SPI를 실험하고 있습니다. 전체 예제는 "module-info.java"없이 JDK 9에서 작동합니다. "module-info.java"를 추가 한 후 ServiceLocator가 구현 클래스를 찾지 못합니다. 혼란스러워서 modulerized 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.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.text.spi; 
public interface TextAPI { 
    String getHelloWorldText(); 
} 

이 인터페이스에 의해 구현되는

그래서 내 예제 프로젝트는 다음과 같습니다 유사하게 :

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

그러면 구현 클래스가 발견되고 텍스트가 인쇄됩니다. 이 두 개의 "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()); 
    } 
} 

은 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

+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

이 구현 주위에 샘플을 제공합니다 .