**注:該原始碼分析對應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