前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java之spi机制简介

java之spi机制简介

作者头像
lyb-geek
发布2019-07-08 16:51:22
1.1K0
发布2019-07-08 16:51:22
举报

一、什么是SPI机制

SPI机制,是一种将服务接口与服务实现分离以达到解耦、大大提升了程序可扩展性的机制。引入服务提供者就是引入了spi接口的实现者,通过本地的注册发现获取到具体的实现类,轻松可插拔,SPI实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载,为某个接口寻找服务实现的机制

二、SPI具体约定

java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

三、应用场景

1、可替换的插件机制

典型应用,jdbc的实现机制。通常各大厂商(如Mysql、Oracle)会根据一个统一的规范(java.sql.Driver)开发各自的驱动实现逻辑。客户端使用jdbc时不需要去改变代码,直接引入不同的spi接口服务即可。Mysql的则是com.mysql.jdbc.Drive,Oracle则是oracle.jdbc.driver.OracleDriver

2、框架的自定义扩展,比如spring的一些接口,阿里的dubbo也是通过spi来实现自定义扩展

四、简单入门示例

用加减乘除来演示

1、定义服务接口

public interface OperationService {
    Object operation(int a, int b);
}

2、定义具体实现类

public class MultiplyOperationService implements OperationService {
    @Override
    public Object operation(int a, int b) {
        int result = a * b;
        System.out.println("multply---> args[a = "+a+",b = "+b+"],result: a * b = "+result );
        return result;
    }
}

3、src/main/resources/下建立/META-INF/services 目录,新增一个以接口命名的文件

4、接口命名的文件填入如下内容

注:文件的内容可以有多行,每行都是该接口对应的具体实现类的全限定名

5、使用 ServiceLoader 来加载配置文件中指定的实现

public OperationService getService(String key) {
        if (StringUtils.isBlank(key)) {
            throw new RuntimeException("key is null");
        }

        key = key.toLowerCase();

        OperationService operationService = serviceMap.get(key);

        if (operationService == null) {
            ServiceLoader<OperationService> services = ServiceLoader.load(OperationService.class);
            Iterator<OperationService> iterator = services.iterator();
            while (iterator.hasNext()) {
                operationService = iterator.next();
                String clzName = operationService.getClass().getSimpleName();
                String type = StringUtils.substring(clzName, 0, StringUtils.lastIndexOf(clzName, OperationService.class.getSimpleName()));
                if (StringUtils.isNotBlank(type)) {
                    type = type.toLowerCase();
                }

                if (type.equals(key)) {
                    serviceMap.put(key, operationService);
                    break;
                }
            }

            operationService = serviceMap.get(key);
        }

        if(operationService == null){
            throw new RuntimeException("operationService is not found with key :"+key);
        }

        return operationService;

    }

6、测试

public static void main(String[] args) {
        ServiceUtil.getInstance().initCache();

        OperationService operationService = ServiceUtil.getInstance().getService("add");

        operationService.operation(10,2);


        operationService = ServiceUtil.getInstance().getService("divide");

        operationService.operation(10,2);


        operationService = ServiceUtil.getInstance().getService("minus");

        operationService.operation(10,2);


        operationService = ServiceUtil.getInstance().getService("multiply");

        operationService.operation(10,2);
    }
<dependency>
            <groupId>com.demo.spi</groupId>
            <artifactId>spi_operation_add</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.demo.spi</groupId>
            <artifactId>spi_operation_minus</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.demo.spi</groupId>
            <artifactId>spi_operation_divide</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.demo.spi</groupId>
            <artifactId>spi_operation_multiply</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

7、运行结果

add---> args[a = 10,b = 2],result: a + b = 12
divide---> args[a = 10,b = 2],result: a / b = 5
minus---> args[a = 10,b = 2],result: a - b = 8
multply---> args[a = 10,b = 2],result: a * b = 20

五、demo地址链接

https://github.com/lyb-geek/spi_demo

六、参考

1、https://www.cnblogs.com/lovesqcc/p/5229353.html

2、https://blog.csdn.net/sigangjun/article/details/79071850

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是SPI机制
  • 二、SPI具体约定
  • 三、应用场景
  • 四、简单入门示例
  • 五、demo地址链接
  • 六、参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档