「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。
1. 什么是SPI
SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在 ClassPath 路径下的 META-INF/services 文件夹查找文件,自动加载文件里所定义的类。
比如你有个接口,现在这个接口有多个实现类,在系统运行的时候,如何知道选择哪个实现类呢?通过 SPI 可以指定默认的配置,根据配置加载具体的某一个实现类,然后用这个实现类的实例对象。
SPI 机制一般用在插件扩展的场景,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,用到你的开源框架里面,从而扩展某个功能,这个时候 SPI 思想就用上了。这一机制为很多框架扩展提供了可能,比如在 Dubbo、JDBC 中都使用到了 SPI 机制。
2. Java 中 SPI 思想的体现
SPI 经典的思想体现,比如说 jdbc。在 Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。但是实际上项目跑的时候,要使用 jdbc 接口的哪些实现类呢?一般来说,我们要根据自己使用的数据库,比如 mysql,你就将 mysql-jdbc-connector.jar 引入进来;oracle,你就将 oracle-jdbc-connector.jar 引入进来。所以为了方便管理,需要定制一个统一的接口,使调用者在调用数据库的时候可以方便的面向统一的接口进行编程。但是问题来了,真正使用的时候到底用哪个实现呢?从哪里找到实现类呢?这个时候就需要用到 SPI 机制。
最常见的,在我们在访问数据库时候用到的 java.sql.Driver 接口:
Java SPI 规定在 classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,然后文件里面记录的是此 jar 包提供的具体实现类的全限定名。这样当我们引用了某个 jar 包的时候就可以去找这个 jar 包的 META-INF/services/ 目录,再根据接口名找到文件,然后读取文件里面的内容去进行实现类的加载与实例化。