SPI 和 API 之间的区别?

新手上路,请多包涵
阅读 707
2 个回答
  • API 是类/接口/方法/…的描述,您 调用和使用 它们来实现目标,并且
  • SPI 是对类/接口/方法/…的描述,您可以 扩展和实现 这些类/接口/方法来实现目标。

换句话说,API 告诉您特定的类/方法为您做了什么,而 SPI 告诉您必须做什么才能符合。

通常API和SPI是分开的。例如,在JDBC Driver 是SPI的一部分:如果你只是想使用JDBC,你不需要直接使用它,但是每个实现JDBC驱动程序的人都必须实现那个类。

然而,有时它们会重叠。 Connection 接口 既是 SPI又是API:你在使用JDBC驱动时常规使用,需要JDBC驱动的开发者实现。

原文由 Joachim Sauer 发布,翻译遵循 CC BY-SA 3.0 许可协议

来自 _Effective Java,第 2 版_:

服务提供者框架是一个系统,其中多个服务提供者实现了一项服务,并且该系统使实现对其客户端可用,从而将它们与实现解耦。

服务提供者框架包含三个基本组件:提供者实现的服务接口;提供者注册 API,系统使用它来注册实现,让客户可以访问它们;和一个服务访问 API,客户端使用它来获取服务的实例。服务访问 API 通常允许但不要求客户端指定一些选择提供者的标准。如果没有这样的规范,API 将返回一个默认实现的实例。服务访问 API 是构成服务提供者框架基础的“灵活静态工厂”。

服务提供者框架的第四个可选组件是服务提供者接口,提供者实现该接口以创建其服务实现的实例。在没有服务提供者接口的情况下,实现通过类名注册并以反射方式实例化(条目 53)。在 JDBC 的情况下,Connection 扮演服务接口的角色,DriverManager.registerDriver 是提供者注册 API,DriverManager.getConnection 是服务访问 API,Driver 是服务提供者接口。

服务提供者框架模式有许多变体。例如,服务访问 API 可以使用适配器模式 [Gamma95, p. 4] 返回比提供者所需的服务接口更丰富的服务接口。 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();
    }
}

原文由 Roman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题