0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是SPI机制

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-08 15:03 次阅读

1、前言

在之前的JVM 分析系列之类加载提到过 Java SPI 机制,主要是类加载器反双亲委派的实现(第三方包不在指定jdk路径,一般类加载器无法加载,需要特殊的ContextClassLoader加载以便使用)。本次将对 SPI机制进行详解,并结合案例介绍其在实际场景中具体使用。

2、什么是SPI机制?

  • SPI(全称:Service Provider Interface),是jdk内置的一种服务提供发现接口机制,旨在由第三方服务实现或扩展为组件,方便开发人员快速集成指定扩展组件满足指定的需求。这对于应用或平台扩展来说,无疑是一种成本较低、动态灵活的方案。
  • SPI机制调度过程(业务调用方可根据加载的扩展实现类实现功能)
  • 调用流程
    图片

3、实现方式及使用场景

鉴于目前实际项目涉及范围,总结出的常见应用场景。

3.1 接口权限定文件名方式

  • 即在resource文件下创建META/services/目录,并在此目录下新建文件,文件名称为接口类权限定文件名,如 com.lgy.spidemo.serviceway.SpiService。(不好理解就是接口类的package地址 + 接口类名)

使用场景一:

  • 场景描述:不同部门类型的员工需要从不同的考勤应用获取出勤信息,如职能部门仅拉取钉钉考勤,业务部门需要拉取钉钉考勤的基础上再结合自研考勤模块数据汇总出勤结果。
  • 实现方式:抽象通用拉取考勤接口,定义不同部门人员考勤统计实现类。
  • 直接上代码:
  • 通用接口:
package com.lgy.spidemo.serviceway;

 /**
  * @description: 考勤接口
  **/
 public interface AttendanceService {
  void pullAttendanceInfos();
 }
  • 职能部门考勤实现类
/**
  * @description: 职能部门考勤实现
  **/
 public class FunctionAttendanceServiceImpl implements AttendanceService  {
  @Override
  public void pullAttendanceInfos() {
   System.out.println(" FunctionAttendanceService implements ...");
   // 逻辑忽略
  }
 }
  • 销售部门考勤实现
/**
  * @description: 销售部门考勤实现
  **/
 public class SaleAttendanceServiceImpl implements AttendanceService  {
  @Override
  public void pullAttendanceInfos() {
   System.out.println(" SaleAttendanceService implements ...");
   // 逻辑忽略
  }
 }
  • 测试类
/**
  * 1、项目的srcmainresources下创建META-INFservices目录
  * 2、META-INFservices的目录下再增加一个配置文件,这个文件必须以接口的全限定类名保持一致 (com.lgy.spidemo.service.SpiService)
  * 3、在配置文件中写入具体实现类的全限定类名,如有多个便换行写入 com.lgy.spidemo.service.impl.SaleAttendanceServiceImpl
 com.lgy.spidemo.service.impl.FunctionAttendanceServiceImpl
  **/
 public class AttendanceServiceTest {
  public static void main(String[] args) {
   ServiceLoader< AttendanceService > services =
      ServiceLoader.load(AttendanceService.class);
   // 省略判断人员部门类型逻辑
   // 测试输出结果,展示实现接口已加载
   for (AttendanceService service : services) {
    service.pullAttendanceInfos();
   }
  }
 }
  • 测试结果如下
// 两个实现类均被加载成功,在实际使用时,可根据需要去调用不同的实现。
     FunctionAttendanceService implements ...
     SaleAttendanceService implements ....
  • 实现类不要标注任何注解,不然Spring在初始化过程中扫描并加载,无法测试。

结合场景一分析:

  • 此场景可以通过自定义实现类的方式满足业务需求(不同部门的考勤规则),有助于业务实现快速迭代,同时也提升了服务架构的可拓展性。
  • 考虑公司组织架构比较复杂,部门职责分的比较细,后续扩展几率比较大,比如职能部门行政类和运营类标准细分,很可能会增加除了考勤之外的各种考核指标等,借鉴此方案可能简单实现并比较方便集成,使得业务间减少依赖,实现解耦的设计模式,因此个人是比较偏向用此方案。
  • 其它应用:如项目中常用的日志也是采用SPI机制,常见的common-logging的LogFatory就是标准SPI接口,有兴趣的可以自行研究。

3.2 spring.factories方式

  • 和上面一样,需要在resource文件下创建META/services/目录,并在此目录下新建文件,区别在于文件名为 spring.factories

使用场景二

  • 场景描述:针对于不同的开发端使用习惯展示不同的接口文档,比如APP端习惯于Swagger,JAVA端喜欢dateway风格,就在不同实例展示不同接口文档。此场景是我臆想出来。
  • 实现方式:构建两种版本的jar包,比如 1.0.0-swagger 、2.0.0-dataway,再对应的包内配置spring.factories内的config配置类。
  • 代码如下:
package com.lgy.spidemo.factoriesway;

 import org.springframework.boot.autoconfigure.AutoConfigurationImportEvent;
 import org.springframework.boot.autoconfigure.AutoConfigurationImportListener;

 /**
  * @description: 自动配置swagger
  **/
 public class SwaggetAutoConfiguration {
  public SwaggetAutoConfiguration() {
   System.out.println(" SwaggetAutoConfiguration init ...");
  }
  // 配置内容省略
 }

 /**
  * @description: 自动配置dataway
  **/
 public class DataWayAutoConfiguration {
  public DataWayAutoConfiguration() {
   System.out.println(" DataWayAutoConfiguration init ...");
  }
  // 配置内容省略
 }

 /**
 * resource/META-INFO/spring.factories 文件内容 *
 * org.springframework.boot.autoconfigure.EnableAutoConfiguration=
   com.lgy.spidemo.factoriesway.SwaggetAutoConfiguration
 * 输出结果:SwaggetAutoConfiguration init ...
 **/
  • 根据spring.factories内配置的类,在springboot启动初始化过程中会自动加载对应的配置,实现所需的接口文档。

结合场景二分析:

  • spring.factories实现机制与上述方式一致,只是实现方式不同,本质目的是通过抽象化类的方式,实现解耦,最终便于扩展
  • 其它使用场景:如spring-boot-autoconfigure-x.x.x.RELEASE.jar,就是通过此方式完成初始化加载。

4、总结

  • 本次讲解的两种方式均是基于SPI机制,可见是多么受开发追捧。当然,还有很多种实现方式,我个人觉得最主要的还是能够在自己的掌控范围内去使用,毕竟有问题可以通过自己的学习理解去解决。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7640

    浏览量

    148509
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1615

    浏览量

    89620
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66784
  • Package
    +关注

    关注

    0

    文章

    26

    浏览量

    10404
  • spring
    +关注

    关注

    0

    文章

    332

    浏览量

    14161
收藏 人收藏

    评论

    相关推荐

    关于SPI通讯的精讲 SPI协议的特点和工作机制

    1、SPI协议简介 1.1 SPI协议概括 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列
    的头像 发表于 05-08 19:55 8989次阅读
    关于<b class='flag-5'>SPI</b>通讯的精讲 <b class='flag-5'>SPI</b>协议的特点和工作<b class='flag-5'>机制</b>

    聊聊Dubbo - Dubbo可扩展机制实战

    OSGI容器Dubbo作为一个框架,不希望强依赖其他的IoC容器,比如Spring,Guice。OSGI也是一个很重的实现,不适合Dubbo。最终Dubbo的实现参考了Java原生的SPI机制,但对其
    发表于 06-04 17:33

    SPI是什么?SPI的特点有哪些呢

    SPI是什么?SPI的特点有哪些呢?STM32的SPI工作机制有哪些呢?
    发表于 11-03 07:14

    RT_SFUD_SPI_MAX_HZ到底是什么作用机制呢?

    设定会导致spi clk 的波形畸变。设定 13mhz时波形:示波器显示频率 25mhz设定 13mhz时波形:示波器显示频率 50mhz疑问:1:RT_SFUD_SPI_MAX_HZ 到底是什么作用机制2:
    发表于 04-14 10:08

    SPI模式下MMC卡的读写机制

    SPI模式下MMC卡的读写机制  多媒体卡MMC(MultiMedia Card)是由美国SanDisk公司和德国Simens公司于1997年共同开发的一种多功能Flash存储设备。基于ARM7芯
    发表于 03-29 15:13 1008次阅读
    <b class='flag-5'>SPI</b>模式下MMC卡的读写<b class='flag-5'>机制</b>

    基于SPI协议的SD卡读写机制与实现方法

    基于SPI协议的SD卡读写机制与实现方法。
    发表于 03-25 11:21 27次下载
    基于<b class='flag-5'>SPI</b>协议的SD卡读写<b class='flag-5'>机制</b>与实现方法

    SPI通信简介

    目录(?)[-]SPI简介SPI特点1采用主-从模式Master-Slave 的控制方式2采用同步方式Synchronous传输数据3数据交换Data Exchanges4 SPI有四种传输模式5
    发表于 12-22 19:14 9次下载
    <b class='flag-5'>SPI</b>通信简介

    源码级深度理解Java SPI

    SPI 配置:Java SPI 机制约定的配置文件,提供查找服务实现类的逻辑。配置文件必须置于 META-INF/services 目录中,并且,文件名应与服务提供者接口的完全限定名保持一致。文件中的每一行都有一个实现服务类的详
    的头像 发表于 11-15 11:38 460次阅读

    JDK内置的一种服务SPI机制

    SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要用于框架中开发,例如Dubbo、Spring
    的头像 发表于 02-15 09:15 595次阅读

    基于spring的SPI扩展机制是如何实现的?

    基本上,你一说是基于 spring 的 SPI 扩展机制,再把spring.factories文件和EnableAutoConfiguration提一下,那么这个问题就答的八九不离十了。
    的头像 发表于 03-07 09:17 700次阅读

    可插拔组件设计机制SPI介绍

    SPI 的全称是 Service Provider Interface, 即提供服务接口;是一种服务发现机制SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。
    的头像 发表于 03-23 09:20 825次阅读

    Java中的SPI动态扩展(下)

    基本上,你一说是基于spring的SPI扩展机制,再把`spring.factories`文件和`EnableAutoConfiguration`提一下,那么这个问题就答的八九不离十了。
    的头像 发表于 03-24 14:27 388次阅读
    Java中的<b class='flag-5'>SPI</b>动态扩展(下)

    Java、Spring、Dubbo三者SPI机制的原理和区别

    其实我之前写过一篇类似的文章,但是这篇文章主要是剖析dubbo的SPI机制的源码,中间只是简单地介绍了一下Java、Spring的SPI机制,并没有进行深入,所以本篇就来深入聊一聊这三
    的头像 发表于 06-05 15:21 438次阅读
    Java、Spring、Dubbo三者<b class='flag-5'>SPI</b><b class='flag-5'>机制</b>的原理和区别

    SPI传输原理 SPI传输机制

    SPI 传输机制 从图可以看出,主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的移位寄存器
    的头像 发表于 07-27 10:43 1536次阅读
    <b class='flag-5'>SPI</b>传输原理 <b class='flag-5'>SPI</b>传输<b class='flag-5'>机制</b>

    SPI的四种传输模式及工作机制分析

    SPI 规定了两个 SPI 设备之间通信必须由主设备 (Master) 来控制次设备 (Slave). 一个 Master 设备可以通过提供 Clock 以及对 Slave 设备进行片选 (Slave Select) 来控制多个 Slave 设备。
    发表于 10-31 09:34 5663次阅读
    <b class='flag-5'>SPI</b>的四种传输模式及工作<b class='flag-5'>机制</b>分析