java之API和SPI


java之API和SPI


JAVA中区分API和SPI都是相对的概念,他们的差别只是在语义上,API直接被应用开发人员使用,API被框架的开发人员使用。

API   

大多数情况下,都是实现方来定制接口并完成对接口的不同实现,调用方仅仅依赖却无权选择不同的实现。

SPI

SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制。本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。

在Java中SPI是被用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。有很多组件的实现,如日志、数据库访问等都是采用这样的方式,最常用的就是 JDBC 驱动。

SPI代码示例

一、项目目录

 二、定义框架接口

public interface Car {

    boolean isSupport(String name);

    void start();

    void druid();

    void stop();


}

 三、定于服务提供方实现,并放入WEN-INFO/services/下

定义宝马汽车驱动

public class BmwCar implements Car {


    private final String BMW = "car:bmw://";

    public boolean isSupport(String name) {

        if(name.startsWith(BMW)){
            return Boolean.TRUE;
        }

        return Boolean.FALSE;

    }

    public void start() {
        System.out.println("------ 宝马 启动 -----------------");
    }

    public void druid() {
        System.out.println("------ 宝马 启动中 -----------------");
    }

    public void stop() {
        System.out.println("------ 宝马 停止 -----------------");
    }

}

定义奥迪汽车驱动

public class AudiCar implements Car {


    private final String AUDI = "car:audi://";

    public boolean isSupport(String name) {

        if(name.startsWith(AUDI)){
            return Boolean.TRUE;
        }

        return Boolean.FALSE;

    }

    public void start() {
        System.out.println("------ 奥迪 启动 -----------------");
    }

    public void druid() {
        System.out.println("------ 奥迪 启动中 -----------------");
    }

    public void stop() {
        System.out.println("------ 奥迪 停止 -----------------");
    }

}

 WEN-INFO/services/

 四、通过ServiceLorder 实现加载不同的厂商驱动

public class Test {


    private final static String NAME = "car:audi://";


    public static void main(String[] args) {

        ServiceLoader spiLoader = ServiceLoader.load(Car.class);

        for (Car spi : spiLoader) {
            if(spi.isSupport(NAME)){
                Travel travel = new Travel(spi);
                travel.go("");
                break;
            }

        }

    }

}