[设计与架构]Java当中的SPI(Service Provider Interface)设计思想(由双亲委派引出的问题)

导言

在看双亲委派机制的时候,有人提到SPI的概念,于是学习了一番。SPI,即Service Provider Interface,服务提供者的接口。这个SPI接口是由服务端提供和调用的,这个接口定义了一些规范,但不提供具体的接口功能,功能由客户端决定,客户端根据需要实现这个接口,并进行配置,将接口的实现实例和配置打包部署在服务端,服务端不会直接调用接口的实现实例,而是 调用SPI接口,其产生的行为取决于配置文件。

SPI设计思想如下图所示:
在这里插入图片描述

SPI接口一般由客户端和服务端共同确定(更多是服务端根据不同客户端的需求,形成一个兼容并包的接口)。客户端根据需求实现这个接口,得到一个自己的实例。服务端会有一个以这个SPI接口为文件名的配置文件,配置文件当中指定服务端将调用哪个客户端的接口实例。

SPI的本质是多态,多态的好处是在解耦的同时,实现了适配。

SPI的实现之ServiceLoader

Java是通过ServiceLoader提供SPI功能的,我们来模拟服务端、客户端的角色,理解SPI是怎么工作的。

场景:不同的数据库想要通过Java连接,必须实现一个规范的接口,并提供相应的JDBC驱动。

一、服务端与客户端协商提供统一的SPI接口

新建一个Java项目,给出统一的SPI接口,代码如下,其中有一个connect()方法。

package com.java.db;

/**
 * @ClassName DBDriver
 * @Description TODO
 * @Date 2021/1/11 22:19
 */
public interface DBDriver {
   
    public String connect();
}

把这个项目打包成jar包,记名为DBDriverInterface.jar

二、客户端提供带有配置文件的驱动类

新建一个Java项目,创建一个MySQLDriver类,实现DBDriver接口,因此这个项目中需要导入DBDriverInterface.jar包,目录结构如下图所示:
在这里插入图片描述
代码如下:

package com.java.mysql.godriver;

import com.java.db.DBDriver;

/**
 * @ClassName MySQLDriver
 * @Description TODO
 * @Date 2021/1/11 22:21
 */
public class MySQLDriver implements DBDriver {
   
    public String connect() {
   
        System.out.println("MySQL连接成功");
        return "一个MySQL连接实例";
    }
}

resources目录下,添加META-INF\services目录,并创建文本文件,文件名为com.java.mysql.DBDriver,就是SPI接口的全名,写入以下内容,这就是接口实现类的全名

com.java.mysql.godriver.MySQLDriver

把这个项目打包成jar包,记名为MySQLDBDriver.jar

三、服务端利用ServiceLoader加载驱接口

利用ServiceLoader加载接口的class对象,就可以加载配置文件当中实现了这个接口的所有驱动类,并执行相应的动作。

新建一个Java项目,导入上述两个包:DBDriverInterface.jar包和MySQLDBDriver.jar包,并利用ServiceLoader去加载MySQL数据库连接驱动,目录结构如下所示:
在这里插入图片描述
主类代码如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值