SPI介绍
Java中SPI的概念是一种服务发现的机制,从1.6开始支持该功能。具体来说就是一个接口有多个实现的时候,可以通过SPI动态加载具体实现。
源码再现
从1.6开始,增加了java.util.ServiceLoader
类,用于扫描某个接口的具体实现类。
public final class ServiceLoader<S>
implements Iterable<S>
{
private static final String PREFIX = "META-INF/services/";
// The class or interface representing the service being loaded
private final Class<S> service;
// The class loader used to locate, load, and instantiate providers
private final ClassLoader loader;
从源码看出,ServiceLoader是一个泛型类,可以指定某个接口,它会扫描META-INF/services/
路径下以相关接口的全路径类名命名的文件,文件中写入所有需要扫描的实现类名即可。
举个例子
1.首先定义一个接口SpiInterface,假如包名为com.spi.test
2.再定义它的若干实现类,假如包名为com.spi.test.impl
3.在META-INF/services/
新建文件com.spi.test.SpiInterface
com.spi.test.impl.ASpiInterface
com.spi.test.impl.CSpiInterface
com.spi.test.impl.BSpiInterface
4.通过ServiceLoader获取实现
ServiceLoader<SpiInterface> loaders = ServiceLoader.load(SpiInterface.class);
for (SpiInterfacein : loaders) {
in.sayHello();
}
应用场景
1.厂家定义接口,如老版本的sql驱动等
2.日志统一接口
3.api版本控制,不同的版本实现可以用继承,根据不同的版本号找对应的实现类
替代方案
自己完成类似SPI的功能,可以使用普通的类加载器去动态加载实现类,也可以使用spring的import org.springframework.context.ApplicationContext
获取。但SPI实现更简单,而且api内置集成,推荐使用。
样列源码
- zj-learn中spi包下代码。
网友评论