当前位置:网站首页>SPI机制
SPI机制
2022-07-03 02:01:00 【xixingzhe2】
1、概念
spi全称为 (Service Provider Interface),是JDK内置的一种服务提供发现机制。SPI是一种动态替换发现的机制,一种解耦非常优秀的思想。它是jdk提供给“服务提供厂商”或者“插件开发者”使用的接口,是一种扩展机制。
2、用途
在面向对象的设计中,模块之间我们一般会采取面向接口编程的方式,而在实际编程过程过程中,API的实现是封装在jar中,当我们想要换一种实现方法时,还要生成新的jar替换以前的实现类。而通过jdk的SPI机制就可以实现,首先不需要修改原来作为接口的jar的情况下,将原来实现的那个jar替换为另外一种实现的jar即可。
总结一下SPI的思想:在系统的各个模块中,往往有不同的实现方案,例如日志模块的方案、xml解析的方案等,为了在装载模块的时候不具体指明实现类,我们需要一种服务发现机制,java spi就提供这样一种机制。有点类似于IoC的思想,将服务装配的控制权移到程序之外,在模块化设计时尤其重要。
示例:重写第三方jar中SPRING BEAN的方式_xixingzhe2的博客-CSDN博客
3、优缺点
3.1 优点
- 为了解耦,将接口和具体实现分离开来。
- 提高框架的扩展性。应用程序可以根据实际业务情况启用框架扩展或替换框架组件,避免接口和实现都写在一起,调用方无权选择使用具体的实现类。
3.2 缺点
- 虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类。
- 多个并发多线程使用ServiceLoader类的实例是不安全的。
4、规范
定义服务的通用接口,针对通用的服务接口,提供具体的实现类。
- 在jar包(服务提供者)的META-INF/services/目录中,新建一个文件,文件名为SPI接口的"全限定名"(如:com.ybw.spi.service.DemoService)。 文件内容为该接口的具体实现类的"全限定名"(如:com.ybw.spi.service.impl.DemoOneServiceImpl)。
- 将spi所在jar放在主程序的classpath中。
- 服务调用方使用java.util.ServiceLoader去动态加载具体的实现类到JVM中。
5、SPI示例
代码结构

模块依赖关系

5.1 spi-service
定义接口
package com.ybw.spi.service;
/**
* Demo service. Implements should be use SPI.
*
* @author ybw
* @version V1.0
* @className DemoService
* @date 2022/6/29
**/
public interface DemoService {
String sayHello();
}5.2 spi-service-impl-one
实现一
package com.ybw.spi.service.impl;
import com.ybw.spi.service.DemoService;
/**
* Implement for DemoService
*
* @author ybw
* @version V1.0
* @className DemoOneServiceImpl
* @date 2022/6/29
**/
public class DemoOneServiceImpl implements DemoService {
@Override
public String sayHello() {
return "hello world one";
}
}META-INF/services/下创建文件com.ybw.spi.service.DemoService,内容为
com.ybw.spi.service.impl.DemoOneServiceImpl5.3 spi-service-impl-two
实现二
package com.ybw.spi.service.impl;
import com.ybw.spi.service.DemoService;
/**
* Implement for DemoService
*
* @author ybw
* @version V1.0
* @className DemoOneServiceImpl
* @date 2022/6/29
**/
public class DemoTwoServiceImpl implements DemoService {
@Override
public String sayHello() {
return "hello world two";
}
}META-INF/services/下创建文件com.ybw.spi.service.DemoService,内容为
com.ybw.spi.service.impl.DemoTwoServiceImpl5.4 spi-execute
执行模块
package com.ybw.spi.test;
import com.ybw.spi.service.DemoService;
import com.ybw.spi.service.impl.DemoOneServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.util.ServiceLoader;
/**
* 加载使用
*
* @author ybw
* @version V1.0
* @className SpiTest
* @date 2022/6/29
**/
@Slf4j
public class SpiTest {
/**
* @methodName: spiTest
* @return: void
* @author: ybw
* @date: 2022/6/29
**/
@Test
public void spiTest() {
ServiceLoader<DemoService> demoServices = ServiceLoader.load(DemoService.class);
demoServices.forEach(demoService -> {
log.info(demoService.getClass().getName());
log.info("ClassLoader:{}",demoService.getClass().getClassLoader());
log.info(demoService.sayHello());
});
}
}引入依赖spi-service-impl-one

输入日志
[INFO ] 2022-06-29 16:12:58.135 [main] com.ybw.spi.test.SpiTest - com.ybw.spi.service.impl.DemoOneServiceImpl
[INFO ] 2022-06-29 16:12:58.146 [main] com.ybw.spi.test.SpiTest - ClassLoader:[email protected]
[INFO ] 2022-06-29 16:12:58.151 [main] com.ybw.spi.test.SpiTest - hello world one
引入的实现模块不同,打印的日志也会不同。
5.5 代码地址
https://gitee.com/xixingzhe2/share/tree/master/spi/spi-jdk-demo
6、spring spi
在springboot的自动装配过程中,最终会加载META-INF/spring.factories文件,而加载的过程是由SpringFactoriesLoader加载的。
从CLASSPATH下的每个Jar包中搜寻所有META-INF/spring.factories配置文件,然后将解析properties文件,找到指定名称的配置后返回。注意的是,其实这里不仅仅是会去ClassPath路径下查找,会扫描所有路径下的Jar包,只不过这个文件只会在Classpath下的jar包中。
可以看另一边文章:spring boot 自定义starter_xixingzhe2的博客-CSDN博客
源代码:https://gitee.com/xixingzhe2/share/tree/master/spring/spring-demo-starter-parent
7、jdk与spring spi区别
| jdk | spring | |
| 加载类不同 | JDK使用的工具类是ServiceLoader | Spring中使用的类是SpringFactoriesLoader,在 org.springframework.core.io.support包中 |
| 文件路径不同 | jdk配置放在META-INF/services/目录中 | spring配置放在 META-INF/spring.factories中 |
边栏推荐
- 转载收录6.5大侠写的部分Qt开发经验
- Learn BeanShell before you dare to say you know JMeter
- Redis: simple use of redis
- Network security - phishing
- [Yu Yue education] Jiujiang University material analysis and testing technology reference
- [leetcode] 797 and 1189 (basis of graph theory)
- Distributed transaction solution
- 力扣(LeetCode)183. 从不订购的客户(2022.07.02)
- How do it students find short-term internships? Which is better, short-term internship or long-term internship?
- 单词单词单词
猜你喜欢

Machine learning notes (constantly updating...)

PyTorch 卷积网络正则化 DropBlock

Y54. Chapter III kubernetes from introduction to mastery -- ingress (27)

Analysis, use and extension of open source API gateway apisex
![[shutter] shutter debugging (debugging fallback function | debug method of viewing variables in debugging | console information)](/img/66/0fda43da0d36fc0c9277ca86ece252.jpg)
[shutter] shutter debugging (debugging fallback function | debug method of viewing variables in debugging | console information)

可視化yolov5格式數據集(labelme json文件)
![[leetcode] 797 and 1189 (basis of graph theory)](/img/2a/9c0a904151a17c2d23dea9ad04dbfe.jpg)
[leetcode] 797 and 1189 (basis of graph theory)

详细些介绍如何通过MQTT协议和华为云物联网进行通信

Wechat applet Development Tool Post net:: Err Proxy Connexion Problèmes d'agent défectueux

技术大佬准备就绪,话题C位由你决定
随机推荐
Query product cases - page rendering data
Cfdiv2 fixed point guessing- (interval answer two points)
【Camera专题】HAL层-addChannel和startChannel简析
stm32F407-------ADC
Network security - vulnerabilities and Trojans
Swift development learning
Analysis, use and extension of open source API gateway apisex
Bottleneck period must see: how can testers who have worked for 3-5 years avoid detours and break through smoothly
可视化yolov5格式数据集(labelme json文件)
How to deal with cache hot key in redis
Everything file search tool
Explore the conversion between PX pixels and Pt pounds, mm and MM
Network security - talking about security threats
[Yu Yue education] reference materials of chemical experiment safety knowledge of University of science and technology of China
easyExcel
y54.第三章 Kubernetes从入门到精通 -- ingress(二七)
深度学习笔记(持续更新中。。。)
Kotlin middle process understanding and Practice (I)
Internal connection query and external connection
【Camera专题】OTP数据如何保存在自定义节点中