Java是如何實現自己的SPI機制的? JDK原始碼(一)
阿新 • • 發佈:2020-03-29
**注:該原始碼分析對應JDK版本為1.8**
# 1 引言
這是【原始碼筆記】的JDK原始碼解讀的第一篇文章,本篇我們來探究Java的SPI機制的相關原始碼。
# 2 什麼是SPI機制
那麼,什麼是SPI機制呢?
SPI是Service Provider Interface 的簡稱,即**服務提供者介面**的意思。根據字面意思我們可能還有點困惑,SPI說白了就是一種擴充套件機制,我們在相應配置檔案中定義好某個介面的實現類,然後再根據這個介面去這個配置檔案中載入這個例項類並例項化,其實SPI就是這麼一個東西。說到SPI機制,我們最常見的就是Java的SPI機制,此外,還有Dubbo和SpringBoot自定義的SPI機制。
有了SPI機制,那麼就為一些框架的靈活擴充套件提供了可能,而不必將框架的一些實現類寫死在程式碼裡面。
那麼,某些框架是如何利用SPI機制來做到靈活擴充套件的呢?下面舉幾個栗子來闡述下:
1. **JDBC驅動載入案例**:利用Java的SPI機制,我們可以根據不同的資料庫廠商來引入不同的JDBC驅動包;
2. **SpringBoot的SPI機制**:我們可以在`spring.factories`中加上我們自定義的自動配置類,事件監聽器或初始化器等;
3. **Dubbo的SPI機制**:Dubbo更是把SPI機制應用的**淋漓盡致**,Dubbo基本上自身的每個功能點都提供了擴充套件點,比如提供了叢集擴充套件,路由擴充套件和負載均衡擴充套件等差不多接近30個擴充套件點。如果Dubbo的某個內建實現不符合我們的需求,那麼我們只要利用其SPI機制將我們的實現替換掉Dubbo的實現即可。
上面的三個栗子先讓我們直觀感受下某些框架利用SPI機制是如何做到靈活擴充套件的。
# 3 如何使用Java的SPI?
我們先來看看如何使用Java自帶的SPI。
先定義一個`Developer`介面
```java
// Developer.java
package com.ymbj.spi;
public interface Developer {
void sayHi();
}
```
再定義兩個`Developer`介面的兩個實現類:
```java
// JavaDeveloper.java
package com.ymbj.spi;
public class JavaDeveloper implements Developer {
@Override
public void sayHi() {
System.out.println("Hi, I am a Java Developer.");
}
}
```
```java
// PythonDeveloper.java
package com.ymbj.spi;
public class PythonDeveloper implements Developer {
@Override
public void sayHi() {
System.out.println("Hi, I am a Python Developer.");
}
}
```
然後再在專案`resources`目錄下新建一個`META-INF/services`資料夾,然後再新建一個以`Developer`介面的全限定名命名的檔案,檔案內容為:
```java
// com.ymbj.spi.Developer檔案
com.ymbj.spi.JavaDeveloper
com.ymbj.spi.PythonDeveloper
```
最後我們再新建一個測試類`JdkSPITest`:
```java
// JdkSPITest.java
public class JdkSPITest {
@Test
public void testSayHi() throws Exception {
Servi