1.什么是SPI
SPI全称Service Provide Interface,是JDK内置的一种服务提供发现机制(如:JDBC)。是一种动态替换发现机制。例如:有个接口想在运行时才发现具体的实现类,那么你只需要在程序运行前添加一个实现即可,并把新加的实现描述给JDK即可。实现类系统类加载器AppClassLoader来加载(注:这里是违反了类加载器双亲委派模式)。
2.SPI规范
3.SPI使用
1.定义接口
2.设置实现类
3.设置类加载配置文件
4.使用
添加依赖
类加载
5.SPI缺点
我们使用SPI查找具体的实现的时候,需要遍历所有的实现,并实例化,然后我们在循环中才能找到我们需要实现。这应该也是最大的缺点,需要把所有的实现都实例化了,即便我们不需要,也都给实例化了。
结果
5.ServiceLoader源码简单分析
1.获取上下文类加载器(App ClassLoader)
/**
*
*获取上下文类加载器
*/
public static <S> ServiceLoader<S> load(Class<S> service) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return ServiceLoader.load(service, cl);
}
2.初始化服务提供者查找的迭代器
public void reload() {
providers.clear();
lookupIterator = new LazyIterator(service, loader);
}
3.服务提供者查找的迭代器
private class LazyIterator
implements Iterator<S>
{
//服务提供者接口 例如:Hello
Class<S> service;
//类加载器
ClassLoader loader;
//保存实现类的url
Enumeration<URL> configs = null;
//保存实现类的名称
Iterator<String> pending = null;
//下一个实现类的名称
String nextName = null;
private LazyIterator(Class<S> service, ClassLoader loader) {
this.service = service;
this.loader = loader;
}
}
4.实现迭代器的方法 在迭代的时候才会去获取具体实现接口的实例
private boolean hasNextService() {
if (nextName != null) {
return true;
}
if (configs == null) {
try {
//获取接口的名称
String fullName = PREFIX + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(fullName);
else
configs = loader.getResources(fullName);
} catch (IOException x) {
fail(service, "Error locating configuration files", x);
}
}
while ((pending == null) || !pending.hasNext()) {
if (!configs.hasMoreElements()) {
return false;
}
//获取所有实现接口的实例名称
pending = parse(service, configs.nextElement());
}
//定义下一个实例的名称
nextName = pending.next();
return true;
}
//获取服务
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
//获取实例的类属性
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
if (!service.isAssignableFrom(c)) {
fail(service,
"Provider " + cn + " not a subtype");
}
try {
//实例化
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated: " + x,
x);
}
throw new Error(); // This cannot happen
}
//实现迭代器的方法
public boolean hasNext() {
if (acc == null) {
return hasNextService();
} else {
PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
public Boolean run() { return hasNextService(); }
};
return AccessController.doPrivileged(action, acc);
}
}
//实现迭代器的方法获取实例化后的对象
public S next() {
if (acc == null) {
return nextService();
} else {
PrivilegedAction<S> action = new PrivilegedAction<S>() {
public S run() { return nextService(); }
};
return AccessController.doPrivileged(action, acc);
}
}