java中spi(service provider interface)是jdk内置的一种服务发现机制,可以基于配置,在运行时加载指定服务。java中提供了很多服务提供接口,如jdbc、jndi等。
面对分布式的开发,很多系统之间的调用都是使用rpc直接调用,但是有的时候上游的系统需要调用下游系统很多的接口,导致开发工作量很大。因此上游系统使用spi的方式在jar包中打一个spi接口,让下游的业务实现这个spi接口,上游的系统则可以通用的调用这一个接口就可以使用不同的功能。
下游业务方的实现:
一般我们需要设计如何实现spi接口,那实现的最简单的方式就是implements这个spi接口,这种实现方式不利用后续的扩展。
新建maven 工程
服务调用者先定制接口结构,然后提供给服务提供者进行实现,服务提供者按照接口规范,实现,然后在resources/META-INF/services目录,然后在下面新建文件,文件名为接口的路径,图为org.springboot.produce.service.IMsgService
文件内容为
里面是接口实现类路径
接口:
public interface IMsgService{
public boolean accept(String msg);
public void sendMsg(String msg);
public String getName();
}
实现KafkaMsgServiceImpl
public class KafkaMsgServiceImpl
@Override
public boolean accept(java.lang.String msg) {
// TODO Auto-generated method stub
if(msg.equals(getName()))
return true;
return false;
}
@Override
public void sendMsg(java.lang.String msg) {
// TODO Auto-generated method stub
System.out.println("KafkaMsgServiceImpl "+msg);
}
@Override
public java.lang.String getName() {
// TODO Auto-generated method stub
return "KafkaMsgServiceImpl";
}
}
实现QueueMsgServiceImpl
public class QueueMsgServiceImpl implements IMsgService{
@Override
public boolean accept(String msg) {
// TODO Auto-generated method stub
if(msg.equals(getName()))
return true;
return false;
}
@Override
public void sendMsg(String msg) {
// TODO Auto-generated method stub
System.out.println("QueueMsgServiceImpl "+msg);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return "QueueMsgServiceImpl";
}
}
然后将springboot-produce工程 maven打包 安装到本地maven仓库 , mvn install命令,打包后 ,别的工程(bundle)就可以依赖进去,进行调用
新建消费者maven工程 springboot-consume
pom.xml (springboot-produce为上面服务提供者的jar,这里要依赖引入)
在springboot-consume新建测试类 App
public class App
{
public static void main( String[] args )
{
ServiceLoader
Iterator
while (iterator.hasNext()) {
IMsgService msgService = iterator.next();
if(msgService.accept(msgService.getName())){
msgService.sendMsg("测试");
}
}
}
}
springboot-consume启动类会扫描本地及依赖包下resources/META-INF/*下 有无以该接口org.springboot.produce.service.IMsgService命名的文件。
运行