SPI全称Service provider interface,是一种服务发现机制。其通过resource/META-INF/services文件来查找具体的实现类,并加载到jvm中,因此可以对现有代码进行灵活的扩展。再此我们先做个小的demo吧。
一般来说我们知道做任何事情都要有个主线,你不能说上了一天班然后该干啥不知道,傻傻呼呼坐了一天,最后整个人都快要废了的感觉。这样的事情在编程这样严密的事情上来说也是站不住脚的,在编程代码编程中大的导向性我们是我们逻辑,在战术层面比较重要的就是接口、父类、虚类这些了。所以说SPI所说的灵活的扩展,不外乎接口、父类以及虚类的情况。So demo来了。
定义接口
package com.example.demo.spi;
/**
* @Author tianjl
* @Date 2021/10/11 10:11
* @Discription disc
*/
public interface MySpi {
void show();
}
实现类1
package com.example.demo.spi.imp;
import com.example.demo.spi.MySpi;
/**
* @Author tianjl
* @Date 2021/10/11 10:12
* @Discription disc
*/
public class MySpi1 implements MySpi {
@Override
public void show() {
System.out.println("this is myspi one~~~~");
}
}
实现类2
package com.example.demo.spi.imp;
import com.example.demo.spi.MySpi;
/**
* @Author tianjl
* @Date 2021/10/11 10:12
* @Discription disc
*/
public class MySpi2 implements MySpi {
@Override
public void show() {
System.out.println("this is myspi two~~~~");
}
}
在main/resources/services目录下创建spi接口类路劲的文件,并将具体的实现类的路径放入其中,如图所示:
在创建好这些类和文件之后,我们需要将我们的spi实现类用起来,所以这块我们要编写主要的调用类。
public class TestSpi {
public static void main(String[] args) {
Iterator providers= Service.providers(MySpi.class);
ServiceLoader loader=ServiceLoader.load(MySpi.class);
while (providers.hasNext()){
MySpi service=providers.next();
service.show();
}
System.out.println("------");
Iterator iterator=loader.iterator();
while (iterator.hasNext()){
MySpi service=iterator.next();
service.show();
}
}
}
运行的结果如下:
如上图所示,spi的demo是跑起来了,我们可以想一下其实这个spi我们完全可以自己搞一套,因为我们读取的接口文件是固定的META-INF/services目录,因为接口路径存在,接口实现类的路径也存在,所以采用jdk的反射轻松就可以进行实例化。
在jdbc中链接的初始化就采用了spi机制。
说到这里,我们就了解了spi到底是个啥了,我们也可以通过java类中的静态代码进行潜移默化的一些事。对于我们要扩展或者摘除的一些类来说,修改services下对应接口文件的内容,并进行重新reload接口文件即可。
午安~