为了更好的理解Dubbo SPI机制,我们首先应该去了解下Java本身自带的SPI机制到底是个什么东西。明白了这个之后,那么Dubbo自己实现的SPI机制无非就是提供了更好的解决方案,以及一些额外的功能而已。其核心目的都是大同小异的。
1.1.那么SPI机制到底是什么呢?
先粘一段官方点的描述:SPI全称Service Provider Interface,从Java6开始被引入,是一种基于ClassLoader来发现并加载服务的机制。
这里我来简单描述下,SPI实际上就是JDK提供一个抽象规范,这里可以简单理解为接口。之后用户可以根据自己的需要来进行定制化实现并且在特定目录下配置好实现的入口,最后通过ClassLoader来进行加载、执行配置文件中配置的对应实现类。以此来达到灵活拓展或者替换对应的实现。类似于插件。常用于数据库框架,日志框架等...
1.2.这里SPI机制解决了什么问题?
这里就以比较常见的数据库驱动来举例吧,因为市面上有很多不同数据库的厂商。我们知道连接数据库需要数据库驱动,如果任由其各自实现,那么就会五花八门难以进行统一的管理。所以我们需要指定一个统一的规范,各厂商得按照这个规范来开发。
再来想想我们最开始学习JDBC的时候是如何加载数据库驱动的,没记错的话是通过”Class.forName("com.mysql.cj.jdbc.Driver");“来进行加载的吧,那么有没有什么办法能不写这种死代码呢?很简单,就是利用SPI机制呀~所以,SPI机制也给我们带来了便利性,我们只需要引入对应数据库的jar包就可以直接获取数据库的连接了。就像这样”Connection connection = DriverManager.getConnection("url");“,是不是很方便。
其实这就是类似于插件的形式来进行解耦。
1.3.接下来看下SPI是如何实现的?
1.3.1.Java SPI都有哪几个重要的组成:
- 接口
- 对应的实现类
- META-INF.services下的配置文件
- ServiceLoader(重中之重)
接口和对应的实现类就不用说了吧,这是最基本的。META-INF.services下的配置文件,这里为什么是这个路径下呢?并且名字和内容有什么要求吗,这些答案都在ServiceLoader中,并且ServiceLoader负责着解析加载类的功能,so~这是我们关注的重点。
ServiceLoader的大体来讲主要流程如下:
1.3.2.ServiceLoader源码分析
既然ServiceLoader的是比较重要的,那么我们就简单来看一下。以一个小demo开始~
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 获取ServiceLoader
ServiceLoader<Driver> load = ServiceLoader.load(Driver.class);
Iterator<Driver> iterator = load.iterator();
// 解析配置文件中的类
if (iterator.ha