何为SPI?
说到SPI大家可能比较陌生,但可能比较熟悉API,两者都属于接口,但是有区别的。
SPI 将服务接口和具体的服务实现分离开来,由调用者制定规范,不同的实现方去实现这套规范。因此在修改或者替换服务实现并不需要修改调用方。
JDK SPI 机制ServiceLoader
主要流程:
1. 通过 URL 工具类从 jar 包的 /META-INF/services
目录下面找到对应的文件,
2. 读取这个文件的名称找到对应的 spi 接口,
3. 通过 InputStream
流将文件里面的具体实现类的全类名读取出来,
4. 根据获取到的全类名,先判断跟 spi 接口是否为同一类型,如果是的,那么就通过反射的 机制构造对应的实例对象,
5. 将构造出来的实例对象添加到 Providers
的列表中。
不难发现,SPI 机制的具体实现本质上还是通过反射完成的!!!。
注意: services 文件夹下文件名一定要是接口的全类名,里面的内容一定要是实现类的全类名,实现类可以有多个,直接换行就好了,有多个实现类的时候,会一个一个的迭代加载。
SPI机制存在什么问题?
1. 需要遍历加载所有的实现类,效率相对较低
2. 当多个 ServiceLoader
同时 load
时,由于没有额外的加锁机制会产生并发问题