2013-05-08 6 views
4

API 사용자로부터 서비스 (인터페이스)의 구현 (구체적인 클래스)을 숨기려고합니다. 구현은 Java API ServiceLoader 메커니즘을 사용하는 팩토리에서 사용자에게 제공됩니다. 이 로더는 구현 클래스가 공개되어 있어야합니다. 구현이 사용자가 직접 의존하지 않는 다른 JAR (API JAR은 제외)에 숨겨져있는 한 괜찮습니다.서비스 구현을 숨기기위한 모범 사례

그러나 쉬운 배포를 위해 기본 구현을 사용하는 JAR의 내용은 API JAR로 압축됩니다. 따라서 사용자는 공개 된 가시성을 가진 기본 구현 클래스가있는 미리 구성된 JAR에 의존합니다. 사람들이 구현을 직접 인스턴스화하지 못하게하는 것은 없습니다. 나는 그것이 가능하기를 원하지 않는다.

내 나쁜 아이디어 :

  • 패키지 개인 구현을로드 할 수 있습니다 ServiceLoader의 자신의 버전을 구현 (? BTW, 왜 자바 API ServiceLoader이 허용하지 않습니다 않습니다)

  • 선박 별도의 API 및 구현 JAR

옳은 길이라고 생각합니까? 어떤 타협이라도?

OSGi 또는 기타 중장비 사용은 의문의 여지가 있습니다.

답변

2

어쩌면이 실망하지만 :

  • 는 별도의 항아리를 확인하고 다른 타사 항아리와 그 넣어.
  • 설치 프로그램/배포 프로세스에서 멋진 패키지를 처리하도록하십시오.
  • 컴파일 타임에는이 jar를 사용할 수 없도록 설정하십시오. maven : <scope>runtime</scope>.

유일한 다른 방법은 javadoc에 @Deprecated이 있고, Java 서비스 API를 사용하여 해당 클래스를 사용하는 방법입니다.

+0

음, 이것이 내가 예상 한 것입니다. 어쩌면 라이브러리가있는 POM 템플릿을 제공 할 수도 있습니다. 하지만 패키지 개인 ServiceLoader도 유효한 방법이 아닌가요? 그 접근법을 분류 할 특별한 이유가 있습니까? 고맙습니다. – Alexander

+0

아니요 패키지 개인도해야합니다. 가장 자주 (저급) 수업 중 일부는 공개되어야합니다. –

0

사람들이 출하 된 클래스를 인스턴스화/액세스하는 것을 쉽게 막을 수 없습니다.

그렇기 때문에 사용중인 ServiceLoader 메커니즘을 간단히 포장하고 구체적인 구현 참조가 아닌 Java 인터페이스를 통해 참조되는 인스턴스화 된 클래스를 제공 할 수 있습니다.

+1

OK * 숨기기 * 아마 잘못된 단어입니다. 리플렉션을 통해 모든 더러운 트릭을 수행 할 수 있습니다. 물론 API는 구현이 아닌 인터페이스만을 참조합니다. 하지만 사람들이 우연히 구현을 인스턴스화 할 수 없도록하려는 경우 (예 : 코드 완성 사용) – Alexander

0

먼저 구현 클래스 패키지를 비공개로 만들고 ServiceLoctor를 사용하여 특정 서비스를 검색하는 것이 좋습니다. 내 프로젝트에서 패키지 구조는 다음과 같다 :

public class ServiceLocator{ 
    private static final Map<String,Service> services; 

    static { 
     services=new HashMap<String,Service>(); 
     services.put("default",new ServiceImplementation());//hide implementation 
    } 
    public Service getService(String name){ 
     return services.get(name); 
    } 

    public registerService(Service service, String name){ 
     services.put(name,service) 
    } 
} 

최종 사용자가 구현 클래스에 액세스 할 수 없습니다, 이후 시간에, 당신이 할 수있는 다음 serviceLocator이 같다

-package 
    |-ServiceInterface(public) 
    |-ServiceImplementation(default,package private) 
    |-ServiceLocator(public) 

다른 구현 클래스를 사용하도록 쉽게 변경할 수 있습니다.

+0

슬프게도 서비스 구현이 제 3 자에 의해 번들 될 수 있기 때문에 슬프게도 나를 위해 작동하지 않습니다. 이 서비스는 다른 개발자가 구현 한 SPI이지만 내 코드가 다른 코드를 알기 전까지는 실행할 수 없습니다. 따라서 아무도 registerService()를 호출 할 수 없습니다. 이것이 ServiceLoader를 사용하는 이유입니다. – Alexander

1

C#에서는 관련 친구 어셈블리에서만 볼 수있는 내부 인터페이스를 만든 다음 인터페이스를 명시 적으로 구현할 수 있습니다. Java에서이 작업을 수행하는 방법을 잘 모르겠지만 개념적으로이 방법을 사용하여이 문제를 해결할 수있었습니다.NET 세계.

EDIT 자바를 인터페이스에 대한 명시 적 구현이 없다고 말할 수 있습니다. FYI에서 명시 적으로 인터페이스를 구현하려면 인터페이스 멤버를 통해 함수 호출을해야하며 구현 클래스의 멤버로 호출 할 수는 없습니다. 이것이 .NET 기술에서 저의 기술이 저에게 도움이되는 이유입니다.

또는, 내가 다른 JAR의 인터페이스를 넣어 제안하고, API와 함께 배포하지 않는

+0

완전히 다른 관점에서 볼 때 실제로 흥미로운 접근 방식입니다. 공유에 감사드립니다. 자바에서는 작동하지 않지만 공유합니다. – Alexander

+0

글쎄, 자바에서 이런 식으로 할 수있는 메커니즘이있을 수 있기를 바랬지 만, 불행히도 그렇지 않습니다. Java로 작업 한 이후로 너무 오래되었습니다. 따라서이 작업에 도움이 될만한 세부 정보는 거의 기억하지 못합니다. –