什么是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