ServiceLoader類加載原理

前言

ServiceLoader是實現(xiàn)SPI一個重要的類。是Mark Reinhold在java1.6引入的類,為了解決接口與實現(xiàn)分離的場景。在資源目錄META-INF/services中放置提供者配置文件,文件名以接口的類名命名,里面的內(nèi)容為需要加載的實現(xiàn)類。然后在app運行時,遇到Serviceloader.load(XxxInterface.class)時,會到META-INF/services的配置文件中尋找這個接口對應(yīng)的實現(xiàn)類全路徑名,然后使用Class.forName()(傳入設(shè)定的類加載器)完成類的加載。

下面分別以JDBC的例子來講解SPI。

ServiceLoader:

在mysql-connector包中已經(jīng)滿足了spi的配置,現(xiàn)在看看DriverManager是如何使用ServiceLoader實現(xiàn)mysql Driver的加載的。

DriverManager(jdk1.8.0_151)中有如下的靜態(tài)代碼塊:

查看loadInitialDrivers()方法,核心代碼如下:

ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);

這句代碼中將線程上下文加載器作為后續(xù)加載實現(xiàn)類的加載器(Thread.currentThread().getContextClassLoader()),如果不設(shè)定的話就使用AppClassLoader作為類加載器。并實例化ServiceLoader 和內(nèi)置的LazyIterator。

LazyIterator:實現(xiàn)懶加載機制,在調(diào)用到hasNextService()和nextService()方法時才去找相應(yīng)目錄下的類名,并加載相應(yīng)的類。

while(driversIterator.hasNext()) {

driversIterator.next();

}



在加載com.mysql.jdbc.Driver的時候Driver類有如下靜態(tài)代碼塊:


可以知道,在加載Driver類的時候會new Driver()類并會注冊到DriverManager中的CopyOnWriteArrayList中。private final static CopyOnWriteArrayListregisteredDrivers =new CopyOnWriteArrayList<>();

總結(jié)

在線程創(chuàng)建過程中可以設(shè)定private ClassLoader contextClassLoader屬性,并在ServerLoader中使用該類加載器,使得父類加載器請求子類加載器去完成類加載的動作,打通了雙親委派模型的層次結(jié)構(gòu)來逆向使用類加載器,打破java推薦的雙親委派模型。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容