1.SPI 简介
SPI 全称为 Service Provider Interface,是一种服务发现机制。
SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。
这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。
简单来说,就是在程序运行的时候,通过/META-INF/services/
下的配置文件来决定加载实现类。
Java SPI
一般命名规则是接口包类名的全称,比如 mysql-connector-java-5.1.49.jar
的文件名叫 java.sql.Driver
但是里面的内容就是实现类的包类名全称com.mysql.cj.jdbc.Driver
使用的时候,可以通过ServiceLoader<Robot> serviceLoader = ServiceLoader.load(Driver.class);
来获取配置加载实现类
举个例子:
写一个接口类,就叫WaiMai
package com.inkyi.blog.example.spi;
public interface Waimai {
void songWaiMai();
}
再写两个子类 饿了么 和 美团
package com.inkyi.blog.example.spi;
public class EleMeWm implements Waimai {
@Override
public void songWaiMai() {
System.out.println("饿了么送外卖");
}
}
package com.inkyi.blog.example.spi;
public class MeituanWm implements Waimai {
@Override
public void songWaiMai() {
System.out.println("美团送外卖");
}
}
接着在META-INF/services
下新建一个文件,名字叫:com.inkyi.blog.example.spi.Waimai
内容如下
com.inkyi.blog.example.spi.EleMeWm
最后我们编写测试类
package com.inkyi.blog.example.spi;
import java.util.ServiceLoader;
public class SpiTest {
public static void main(String[] args) {
ServiceLoader<Waimai> load = ServiceLoader.load(Waimai.class);
for (Waimai demo : load) {
demo.songWaiMai();
}
}
}
执行后,Java会根据Waimai.class
的包路径,找到META-INF/services
下的com.inkyi.blog.example.spi.Waimai
文件读取里面的内容,根据内容实例化类,然后执行songWaiMai()
方法。
饿了么送外卖
大概的流程就是这样的,由于ServiceLoader
实现了Iterable
接口,所以com.inkyi.blog.example.spi.Waimai
文件中可以写多个实现类,。
比如把美团和饿了么都加上
com.inkyi.blog.example.spi.MeituanWm
com.inkyi.blog.example.spi.EleMeWm
那么就会输出:
美团送外卖
饿了么送外卖