什么是SPI
SPI(Service Provider Interface)服务提供接口,是指的一种服务发现机制,为某个特定的接口寻找服务的实现。在大规模的软件开发中经常采用这样的机制,实现模块之间基于接口编程,隐藏其实现细节,不同的服务提供商进行扩展实现,最终实现无需修改代码即可调用,实现完全无代码入侵。
JDK自带的SPI实例
JDK6以后提供了java.util.ServiceLoader类来实现从配置文件中加载子类或者接口的实现类。
从JDK API文档中我们可以知道实现起来相当简单,只需四步:
1.定义接口
package com.xxz.service;
public interface HelloService {
public String sayHello();
}
2.写2个实现类,必须是有无构造函数的类
package com.xxz.service.impl;
public abstract class AbstractServiceImpl {
//定义一些实现类都需要的属性
private String name;
public void func(String name){
this.name = name;
}
}
package com.xxz.service.impl;
import com.xxz.service.HelloService;
public class HelloServiceImpl1 extends AbstractServiceImpl implements HelloService{
public String sayHello() {
return "HelloServiceImpl1 sar hello!";
}
}
package com.xxz.service.impl;
import com.xxz.service.HelloService;
public class HelloServiceImpl2 extends AbstractServiceImpl implements HelloService {
public String sayHello() {
return "HelloServiceImpl2 say hello!";
}
}
3.在资源目录 META-INF/services 中放置提供者配置文件,文件名为文件名称为接口类的完整包路径和类名
com.xxz.service.impl.HelloServiceImpl1
com.xxz.service.impl.HelloServiceImpl2
4.测试调用
package com.xxz.service;
import java.util.ServiceLoader;
public class MainBootstrap {
public static void main(String[] args) {
ServiceLoader<HelloService> loadServices = ServiceLoader.load(HelloService.class);
for(HelloService helloService : loadServices){
System.out.println(helloService.sayHello());
}
}
}
执行后打印结果:
HelloServiceImpl1 sar hello!
HelloServiceImpl2 say hello!
JDK自带的ServiceLoader功能比较弱,只提供了如下几个方法:
1.reload:清除服务实例缓存,重新加载;
2.iterator:延迟方式加载服务,按配置的顺序生成服务实例;
3.load:从上下文加载器(ContextClassLoader)加载。
4.loadInstalled,系统加载器(SystemClassLoader)优先,没有则从上下文加载器加载。
实际上,JDK自带的ServiceLoader并不能满足开发的需求,例如单例服务,按别名使用指定的服务实现,优先级控制等等。
本文所涉及的源码:https://download.csdn.net/download/xiongxianze/10453611