文章目录
- 前言
- 一、热插拔(spi机制)是什么?
- 二、使用步骤
- 1.利用java META-INF
- 2.利用google spi
- 3. 测试效果
- 总结
前言
在项目中,如果想要增加项目的灵活性,健壮性, 高逼格,那么你要对于java中的一些机制有了解;
例如:
- java中的spi机制
- spring中的spring.factories 等
这里重点说明spi机制,其实 spring中的spring.factories文件与spi机制类似,这里给大家留个小作业,去自己看吧~
一、热插拔(spi机制)是什么?
SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制,可以轻松实现面向服务的注册与发现,完成服务提供与使用的解耦,并且可以实现动态加载。
引入服务提供者就是引入了SPI接口的实现者,通过本地的注册发现获取到具体的实现类,轻松可插拔,SPI实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载,为某个接口寻找服务实现的机制。
说人话就是:
通过它可以实现 某个接口的策略灵活选择一个实现类,并且可以利用更改配置文件,或者选择内容的机制(甚至通过程序改变), 无需重启服务,即可切换实现类,完成 “热插拔”,像使用一些组件一样,灵活添加,卸载掉 功能实现类;
以程序中常见的, 策略模式为例:
- 登录接口
- 登录接口实现类: 手机登录(1) 用户名密码登录(2) 邮箱登录(3)
- 项目中三个实现类都有,多个环境部署给不同用户, 要求如下
- A 环境采用 1 2 登录, B环境采用 2 登录, C 环境采用 23 登录 ,D 环境采用 123 登录
展示吧~~ 咋弄吧? 一个环境一个环境的改代码? 把多余的实现类删掉?
这里就可以通过spi机制,灵活的配置每个环境的实现类,达到上述要求
二、使用步骤
1.利用java META-INF
- 创建接口
// 接口
public interface SpiService {
void sout();
}
- 创建实现类
// 实现类
public class SpiServiceImpl implements SpiService {
@Override
public void sout() {
System.out.println("SpiServiceImpl 被调用");
}
}
- 在resource文件夹下创建文件夹(META-INF.services)以及文件
- 文件名称 接口全路径 : com.pdf.word.service.SpiService
- 文件内容 接口实现类全路径 : com.pdf.word.service.impl.SpiServiceImpl
2.利用google spi
- 创建接口
public interface GoogleSpiService {
void sout();
}
- 创建实现类
- 引入google,在实现类上加入@AutoService(接口.class)
@AutoService(GoogleSpiService.class)
public class GoogleSpiServiceImpl implements GoogleSpiService {
@Override
public void sout() {
System.out.println("GoogleSpiService 被调用");
}
}
3. 测试效果
创建一个测试类
class SpiServiceTest {
public static void main(String[] args) {
/**---------------------------利用java META-INF ----------------------------------------**/
ServiceLoader<SpiService> load = ServiceLoader.load(SpiService.class);
List<SpiService> spiServiceList = load.stream().map(ServiceLoader.Provider::get).toList();
for (SpiService spiService : spiServiceList) {
spiService.sout();
}
/**---------------------------利用google spi ----------------------------------------**/
ServiceLoader<GoogleSpiService> load1 = ServiceLoader.load(GoogleSpiService.class);
List<GoogleSpiService> spiServiceList1 = load1.stream().map(ServiceLoader.Provider::get).toList();
for (GoogleSpiService spiService : spiServiceList1) {
spiService.sout();
}
}
}
运行后,打印如下:
总结
通过两种方式都可以实现spi机制的调用,这里展示简单调用,当项目中有多个实现类的时候,就可以灵活多变的实现热插拔效果了~
- 利用java META-INF
想用哪个,哪些实现类,就在文件中写哪些实现类的类全路径,每个实现类独占一行 - 利用google spi
想用哪个,哪些实现类,就在相应的实现类上加注解就行了