[java] SPI와 API의 차이점은 무엇입니까?

SPI (Service Provider Interface)API (Application Programming Interface ) 의 차이점은 무엇입니까 ?

보다 구체적으로, Java 라이브러리의 경우이를 API 및 / 또는 SPI로 만드는 이유는 무엇입니까?



답변

  • API는 목표를 달성하기 위해 호출하고 사용 하는 클래스 / 인터페이스 / 방법 / …에 대한 설명입니다.
  • SPI는 목표를 달성하기 위해 확장하고 구현 하는 클래스 / 인터페이스 / 방법 / …에 대한 설명입니다 .

다르게 말하면, API는 특정 클래스 / 방법이 무엇을하는지 알려주고 SPI는 준수하기 위해 무엇을해야하는지 알려줍니다.

일반적으로 API와 SPI는 별개입니다. 예를 들어, JDBC 에서 Driver클래스 는 SPI의 일부입니다. 단순히 JDBC를 사용하려면 직접 사용할 필요는 없지만 JDBC 드라이버를 구현하는 모든 사람이 해당 클래스를 구현해야합니다.

그러나 때로는 겹칩니다. 인터페이스 입니다 모두 SPI 및 API : 당신이 JDBC 드라이버를 사용하고 JDBC 드라이버의 개발자에 의해 구현 될 필요가있을 때 당신은 정기적으로 그것을 사용할 수 있습니다.Connection


답변

에서 효과적인 자바, 제 2 판 :

서비스 제공 업체 프레임 워크는 여러 서비스 제공 업체가 서비스를 구현하는 시스템이며, 시스템은 구현을 클라이언트와 분리하여 구현에서 분리합니다.

서비스 제공자 프레임 워크에는 3 가지 필수 구성 요소가있다 : 제공자가 구현하는 서비스 인터페이스; 시스템이 구현을 등록하는 데 사용하여 클라이언트에게 액세스를 제공하는 제공자 등록 API; 및 클라이언트가 서비스의 인스턴스를 얻기 위해 사용하는 서비스 액세스 API를 포함한다. 서비스 액세스 API는 일반적으로 클라이언트가 공급자 선택을위한 몇 가지 기준을 지정하도록 허용하지만 요구하지는 않습니다. 이러한 사양이 없으면 API는 기본 구현 인스턴스를 반환합니다. 서비스 액세스 API는 서비스 제공 업체 프레임 워크의 기초를 형성하는 “유연한 정적 팩토리”입니다.

서비스 제공자 프레임 워크의 선택적 네 번째 구성 요소는 서비스 제공자 인터페이스로, 제공자는 서비스 구현 인스턴스를 작성하기 위해 구현합니다. 서비스 프로 바이더 인터페이스가없는 경우, 구현은 클래스 명으로 등록되어 반영 적으로 인스턴스화됩니다 (아이템 53). JDBC의 경우 Connection은 서비스 인터페이스의 일부를 재생하고 DriverManager.registerDriver는 제공자 등록 API이고 DriverManager.getConnection은 서비스 액세스 API이며 Driver는 서비스 제공자 인터페이스입니다.

서비스 제공자 프레임 워크 패턴에는 여러 가지 변형이 있습니다. 예를 들어, 서비스 액세스 API는 어댑터 패턴 [Gamma95, p. 5]을 사용하여 공급자에게 필요한 것보다 더 풍부한 서비스 인터페이스를 반환 할 수 있습니다. 139]. 다음은 서비스 제공자 인터페이스 및 기본 제공자를 사용한 간단한 구현입니다.

// Service provider framework sketch

// Service interface
public interface Service {
    ... // Service-specific methods go here
}

// Service provider interface
public interface Provider {
    Service newService();
}

// Noninstantiable class for service registration and access
public class Services {
    private Services() { }  // Prevents instantiation (Item 4)

    // Maps service names to services
    private static final Map<String, Provider> providers =
        new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";

    // Provider registration API
    public static void registerDefaultProvider(Provider p) {
        registerProvider(DEFAULT_PROVIDER_NAME, p);
    }
    public static void registerProvider(String name, Provider p){
        providers.put(name, p);
    }

    // Service access API
    public static Service newInstance() {
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name) {
        Provider p = providers.get(name);
        if (p == null)
            throw new IllegalArgumentException(
                "No provider registered with name: " + name);
        return p.newService();
    }
}


답변

API와 SPI의 차이점은 API가 구체적인 구현을 추가로 제공 할 때 발생합니다. 이 경우 서비스 제공 업체는 몇 가지 API (SPI)를 구현해야합니다.

예를 들면 JNDI입니다.

JNDI는 컨텍스트 조회를위한 인터페이스 및 일부 클래스를 제공합니다. 컨텍스트를 조회하는 기본 방법은 IntialContext에서 제공됩니다. 이 클래스는 내부적으로 공급자 별 구현을 위해 SPI 인터페이스 (NamingManager 사용)를 사용합니다.

이해를 돕기 위해 아래의 JNDI 아키텍처를 참조하십시오.

여기에 이미지 설명을 입력하십시오


답변

API 는 응용 프로그래밍 인터페이스 (Application Programming Interface)의 약자이며, 여기서 API는 일종의 소프트웨어 또는 플랫폼에서 제공하는 서비스 / 기능에 액세스하기위한 수단입니다.

SPI 는 SPI가 소프트웨어 또는 플랫폼의 동작을 주입, 확장 또는 변경하는 방법 인 서비스 제공자 인터페이스를 나타냅니다.

API는 일반적으로 클라이언트가 서비스에 액세스하기위한 대상이며 다음과 같은 속성을 갖습니다.

-> API는 특정 행동이나 결과를 얻기 위해 서비스에 액세스하는 프로그래밍 방식입니다

-> API 진화 관점에서 클라이언트에 대한 추가는 전혀 문제가되지 않습니다.

-> 그러나 클라이언트가 API를 한 번 사용하면 클라이언트 기대가 완전히 저하되므로 적절한 통신이 없으면 변경 / 삭제할 수 없습니다.

다른 쪽의 SPI는 공급자를 대상으로하며 다음과 같은 속성을 갖습니다.

-> SPI는 소프트웨어 또는 플랫폼의 동작을 확장 / 변경하는 방법입니다 (프로그래밍 가능 대 프로그래밍 방식)

-> SPI 진화는 API 진화와 다릅니다 .SPI 제거는 문제가 아닙니다.

-> SPI 인터페이스를 추가하면 문제가 발생하고 기존 구현이 중단 될 수 있습니다

자세한 내용은 여기를 클릭하십시오 : 서비스 제공 업체 인터페이스


답변

NetBeans의 FAQ : SPI 란 무엇입니까? API와 어떻게 다릅니 까?

API는 일반적인 용어-응용 프로그래밍 인터페이스 (Application Programming Interface)의 약어로, 소프트웨어가 노출하는 무언가 (Java, 일반적으로 일부 Java 클래스)를 의미하므로 다른 소프트웨어와 통신 할 수 있습니다.

SPI는 Service Provider Interface의 약어입니다. 라이브러리가 애플리케이션 (또는 API 라이브러리)에 의해 호출되는 클래스를 제공하고 일반적으로 애플리케이션이 수행 할 수있는 작업을 변경하는 상황에 따라 API에 고유 할 수있는 모든 것의 서브 세트입니다.

전형적인 예는 JavaMail입니다. API에는 두 가지 측면이 있습니다.

  • API 쪽-메일 클라이언트를 작성하거나 사서함을 읽으려는 경우 호출
  • JavaMail이 뉴스 또는 IMAP 서버와 같은 새로운 종류의 서버와 통신 할 수 있도록 와이어 프로토콜 핸들러를 제공하는 경우 SPI 측

API 사용자는 거의 SPI 클래스를 보거나 대화 할 필요가 없으며 그 반대도 마찬가지입니다.

NetBeans에서 SPI라는 용어를 볼 때 일반적으로 NetBeans가 새로운 작업을 수행 할 수 있도록 런타임에 모듈이 주입 할 수있는 클래스에 대해 이야기합니다. 예를 들어, 버전 제어 시스템을 구현하기위한 일반적인 SPI가 있습니다. 다른 모듈은 CVS, Subversion, Mercurial 및 기타 개정 제어 시스템을 위해 해당 SPI를 구현합니다. 그러나 파일을 처리하는 코드 (API 측)는 버전 제어 시스템이 있는지 또는 그것이 무엇인지 신경 쓸 필요가 없습니다.


답변

많이 강조되지는 않지만 API / SPI 분할이 존재하는 이유를 이해하는 것이 매우 중요합니다.

API / SPI 분할은 플랫폼이 발전 할 것으로 예상되는 경우에만 필요합니다. API를 작성하고 “알고” 향후 개선이 필요하지 않은 경우 코드를 두 부분으로 분할 할 실제 이유는 없습니다 (깨끗한 객체 디자인을 만드는 것 외에도).

그러나 이것은 거의 사실이 아니며 사람들은 API를 이전 버전과 호환되는 방식으로 미래의 요구 사항과 함께 자유롭게 발전시킬 수 있어야합니다.

위의 모든 내용은 모든 클라이언트 코드가 제어되는 다른 사용자가 자신의 API를 사용 및 / 또는 확장하는 플랫폼을 구축한다고 가정하므로 필요한 경우 리팩터링 할 수 있습니다.

잘 알려진 자바 객체 중 하나를 표시 할 수 있습니다 CollectionCollections.


API : Collections 일련의 유틸리티 정적 메소드입니다. API 객체를 나타내는 클래스는 final클라이언트가 해당 객체를 “구현” 할 수 없으며 정적 메소드 “호출” 에 의존 할 수 있도록 (컴파일 타임에) 정의되는 경우가 많습니다.

Collections.emptySet();

모든 클라이언트가 “호출” 하지만 “구현” 이 아니기 때문에 JDK 작성자 는 이후 버전의 JDK에서 객체에 새로운 메소드자유롭게 추가 할 수 있습니다Collections . 사용 횟수가 많더라도 클라이언트를 중단 할 수 없음을 확신 할 수 있습니다.


SPI : Collection 누구나 자신의 버전을 구현할 수있는 인터페이스입니다. 따라서 JDK 작성자는 자체 구현 (*) 을 작성한 모든 클라이언트를 손상 시킬 수 있으므로 새 메소드를 추가 할 수 없습니다Collection .

일반적으로 추가 방법을 추가 Collection2해야하는 경우 이전 인터페이스 를 확장하는 새 인터페이스 를 만들어야합니다. 그런 다음 SPI 클라이언트는 새 버전의 SPI로 마이그레이션하고 추가 방법을 구현할지 아니면 이전 방법을 고수할지 여부를 결정할 수 있습니다.


당신은 이미 요점을 보았을 것입니다. 두 조각을 하나의 클래스로 결합하면 API가 추가되지 않도록 차단됩니다. 이는 우수한 Java API 및 프레임 워크가 abstract class이전 버전과의 호환성과 관련하여 향후 발전을 차단할 것이므로 노출하지 않는 이유이기도합니다 .

여전히 확실하지 않은 부분이 있으면 위 내용을 자세히 설명하는 이 페이지 를 확인하는 것이 좋습니다 .


(*) 이는 default인터페이스에 정의 된 메소드 개념을 도입 한 Java 1.8까지만 적용됩니다 .


답변

API의 특정 기능을 구현 한 다음 서비스 조회 메커니즘을 통해 사용 가능한 것으로 등록하여 SPI를 더 큰 시스템으로 슬롯을 할당한다고 가정합니다. API는 최종 사용자 응용 프로그램 코드에서 직접 사용하지만 SPI 구성 요소를 통합 할 수 있습니다. 캡슐화와 직접 사용의 차이점입니다.