目录
一、什么是SPI机制
二、spring的spi机制
2.1代码实现
我们先来用代码体验一下 再去深究其原理问题,
项目结构
2.2 SPI 我们都要了解什么
首先我们要探知挖透 spi机制 我们要了解的技术点有 类加载机制 类加载器 双亲委派模型
定义接口层
package com.mb.javaspi;
/**
* 调用 需要移步 text 模块
*/
public interface SpringSpiDemoService {
void show();
}
定义两个实现类
package com.mb.javaspi;
package com.mb.javaspi.impl;
import com.mb.javaspi.SpringSpiDemoService;
/**
* 实现类一
*/
public class SpringSpiDemoServiceImpl1 implements SpringSpiDemoService {
@Override
public void show() {
System.out.println("this is SpringSpiDemoImpl【1】 instantiation class");
}
}
package com.mb.javaspi.impl;
import com.mb.javaspi.SpringSpiDemoService;
/**
* 实现类二
*/
public class SpringSpiDemoServiceImpl2 implements SpringSpiDemoService {
@Override
public void show() {
System.out.println("this is SpringSpiDemoImpl【2】 instantiation class");
}
}
在WEB-INF下面建立services 文件夹 并且建立和接口名字相同的文件 存放实现类的全类名
调用接口 实现api机制
package run;
import com.mb.javaspi.SpringSpiDemoService;
//import sun.misc.Service;
import java.util.Iterator;
import java.util.ServiceLoader;
public class Test {
public static void main(String[] args) {
// Iterator<SpringSpiDemoService> providers = Service.providers(SpringSpiDemoService.class);
ServiceLoader<SpringSpiDemoService> load = ServiceLoader.load(SpringSpiDemoService.class);
/* while(providers.hasNext()) {
SpringSpiDemoService ser = providers.next();
ser.show();
}*/
System.out.println("--------------------------------");
Iterator<SpringSpiDemoService> iterator = load.iterator();
while(iterator.hasNext()) {
SpringSpiDemoService ser = iterator.next();
ser.show();
}
}
}
经上面我们就可以将 接口下面的实现类罗列出来
2.3 spring的spi机制(代码解读)
jdk 8 的 ServiceLoader
public final class ServiceLoader<S> implements Iterable<S>
//配置文件的路径
private static final String PREFIX = "META-INF/services/";
//加载的服务类或接口
private final Class<S> service;
//已加载的服务类集合
private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
//类加载器
private final ClassLoader loader;
//内部类,真正加载服务类
private LazyIterator lookupIterator;
}
jdk 11 的 ServiceLoader
public final class ServiceLoader<S>
implements Iterable<S>
{
// //加载的服务类或接口
private final Class<S> service;
// 装载属性
private final String serviceName;
// The module layer used to locate providers; null when locating
// providers using a class loader
private final ModuleLayer layer;
// The class loader used to locate, load, and instantiate providers;
// null when locating provider using a module layer
private final ClassLoader loader;
// The access control context taken when the ServiceLoader is created
private final AccessControlContext acc;
// The lazy-lookup iterator for iterator operations
private Iterator<Provider<S>> lookupIterator1;
private final List<S> instantiatedProviders = new ArrayList<>();
// The lazy-lookup iterator for stream operations
private Iterator<Provider<S>> lookupIterator2;
private final List<Provider<S>> loadedProviders = new ArrayList<>();
private boolean loadedAllProviders; // true when all providers loaded
总共有三个 ServiceLoader 的构造方法 三个方法的作用
1、初始化此类的新实例以查找服务提供程序
2、@ServiceConfigurationError 如果{@code-svc}无法被{@codecaller}或调用方访问
3、@apiNote供ResourceBundle使用
这个方法 主要是 创建了一些属性,重要的是实例化了内部类,LazyIterator。
三、springboot的spi机制:
3.1 代码实现
SpringBoot-autoconfigure 也可以叫自动装配