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文章
8691浏览量
151804 -
SPI
+关注
关注
17文章
1721浏览量
92039 -
代码
+关注
关注
30文章
4823浏览量
68970 -
Package
+关注
关注
0文章
26浏览量
10542 -
spring
+关注
关注
0文章
340浏览量
14378
发布评论请先 登录
相关推荐
关于SPI通讯的精讲 SPI协议的特点和工作机制
1、SPI协议简介 1.1 SPI协议概括 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列
SPI总线学习笔记
SPI是一种全双工的串行通信总线,最早由Motorola提出,虽然应用广泛,但没有一个统一的总线标准。相较于IIC总线,SPI具有通信速度快、协议灵活、无复杂的总线仲裁机制、支持中断等优点,但缺点也
发表于 09-20 15:17
•1173次阅读
聊聊Dubbo - Dubbo可扩展机制实战
OSGI容器Dubbo作为一个框架,不希望强依赖其他的IoC容器,比如Spring,Guice。OSGI也是一个很重的实现,不适合Dubbo。最终Dubbo的实现参考了Java原生的SPI机制,但对其
发表于 06-04 17:33
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
•1231次阅读
SPI总线协议的工作机制解析
SPI,串行外围设备接口,是Motorola公司推出的一种同步串行接口技术.SPI总线在物理上是通过接在外围设备微控制器(PICmicro)上面的微处理控制单元(MCU)上叫作同步串行端口
发表于 08-25 17:38
•1433次阅读
SPI通信简介
目录(?)[-]SPI简介SPI特点1采用主-从模式Master-Slave 的控制方式2采用同步方式Synchronous传输数据3数据交换Data Exchanges4 SPI有四种传输模式5
发表于 12-22 19:14
•9次下载
源码级深度理解Java SPI
SPI 配置:Java SPI 机制约定的配置文件,提供查找服务实现类的逻辑。配置文件必须置于 META-INF/services 目录中,并且,文件名应与服务提供者接口的完全限定名保持一致。文件中的每一行都有一个实现服务类的详
JDK内置的一种服务SPI机制
SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要用于框架中开发,例如Dubbo、Spring
基于spring的SPI扩展机制是如何实现的?
基本上,你一说是基于 spring 的 SPI 扩展机制,再把spring.factories文件和EnableAutoConfiguration提一下,那么这个问题就答的八九不离十了。
可插拔组件设计机制—SPI介绍
SPI 的全称是 Service Provider Interface, 即提供服务接口;是一种服务发现机制,SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。
Java、Spring、Dubbo三者SPI机制的原理和区别
其实我之前写过一篇类似的文章,但是这篇文章主要是剖析dubbo的SPI机制的源码,中间只是简单地介绍了一下Java、Spring的SPI机制,并没有进行深入,所以本篇就来深入聊一聊这三
SPI传输原理 SPI传输机制
SPI 传输机制 从图可以看出,主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的移位寄存器
评论