基于Spi实现服务高扩展

152 阅读1分钟

简介

Spi(service provider interface)服务发现接口。在面向接口编程中,可以实现插件式的可插拔的选中接口的实现者,来实现高扩展。在dubbo、jdk、jctools等开源项目中都有使用。 在jdk中提供了ServiceLoader来实现Spi。

ServiceLoader简介

官方文档描述

A facility to load implementations of a service. A ServiceLoader is an object that locates and loads service providers deployed in the run time environment at a time of an application's choosing.

使用步骤

  1. Designing services
  2. Developing service providers
  3. Deploying service providers as modules
  4. Deploying service provider on the class path
  5. Obaining a service loader

实操

image.png

  1. api 定义服务接口
  2. api_v1 服务实现v1版本
  3. api_v2 服务实现v2版本
  4. spi_test 测试模块

定义接口模块api

public interface HelloService {
    void hello();
}

服务实现v1、v2

v1实现

public class HelloServiceImpl implements HelloService {
    @Override
    public void hello() {
        System.out.println("hello...v1");
    }
}

v2实现

public class HelloServiceImplV2 implements HelloService {
    @Override
    public void hello() {
        System.out.println("hello...v2");
    }
}

测试类spi_test

pom.xml 添加对应的依赖(接口+实现)

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>api_v1</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>api_v2</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

定义MATA-INF/services 配置文件

image.png 其中文件名为接口的完全限定名,内容为接口实现类的完全限定名。每个实现类独占一行。 META-INF/services/org.example.api.HelloService

org.example.service.HelloServiceImpl
org.example.service.HelloServiceImplV2

加载对应的服务

通过ServiceLoader::load进行加载对应的服务实现者

public class App 
{
    public static void main( String[] args )
    {
        ServiceLoader.load(HelloService.class).forEach(helloService -> {
            helloService.hello();
        });
    }
}

打印结果:

hello...v1
hello...v2

扩展

也可以基于SpringBoot的Conditional来实现Spi,根据配置情况来决定怎么使用扩展。