雖然有SPI破壞雙親委派模型的說法,但我不太認同。簡單說下。java
雙親委派模型(再次吐槽下這個翻譯),是一種加載類的約定。這個約定的一個用處是保證安全。好比說你寫Java用了String類,你怎麼保證你用的那個String類就是JDK裏提供的那個String類呢?答案是對於JDK基礎類,JDK要用特殊的ClassLoader來保證在正確的位置加載。JDK主要有3個自帶ClassLoader:mysql
•最基礎:Bootstrap ClassLoader(加載JDK的/lib目錄下的類)次基礎:Extensionsql
•ClassLoader(加載JDK的/lib/ext目錄下的類)數據庫
•普通:Application ClassLoader(程序本身classpath下的類)編程
雙親委派模型要求若是一個類能夠被委派最基礎的ClassLoader加載,就不能讓高層的ClassLoader加載。這樣你就知道你用的String類必定是被BootstrapClasserLoader加載的/lib下的那個rt.jar的那個java/lang/String.class.安全
但這個模型不是強制的。若是你本身寫個本身的ClassLoader,你能夠不理會它。好比你能夠寫個本身的ClassLoader去本身規定的一個神怪的目錄里加載本身寫的String.class。固然Java Runtime可以識別出這倆String不是一個類,哪怕他們的Full Qualified Class Name如出一轍。因此若是你這作了,大機率是自食其果。當若是你真的知道本身在幹啥,是可以玩出一些花的。服務器
順便說一句,這個機制的安全性是有限的。假若有人能登入服務器,可以直接替換JDK目錄的文件。上述機制也就失效了。爲了保證嚴格的安全,還應該保證系統文件要作數字簽名。編碼
另一點是,這個模式雖然「安全「,可是損失了一丟丟靈活性。就好比java.sql.Driver這個東西。JDK只能提供一個規範接口,而不能提供實現。提供實現的是實際的數據庫提供商。提供商的庫總不能放JDK目錄裏吧。spa
ava從1.6搞出了SPI就是爲了優雅的解決這類問題——JDK提供接口,供應商提供服務。編程人員編碼時面向接口編程,而後JDK可以自動找到合適的實現,豈不是很爽?翻譯
可是便利的同時也帶來了困擾。提供商提供的類不能放JDK裏的lib目錄下,因此也就無法用BootstrapClassLoader加載了。因此當你代碼寫了
Class clz = Class.forName("java.sql.Driver"); Driver d = (Driver)clz.newInstance();
時,這個代碼會用Bootstrap ClassLoader嘗試去加載.問題是java.sql.Driver是個接口,沒法真的實例化,就報錯了。
沒有SPI時,你能夠如今classpath里加一個mysql-connector-java.jar,而後這樣寫
Class clz = Class.forName("com.mysql.jdbc.Driver"); Driver d = (Driver) clz.newInstance();
這就沒問題了,這裏用了Application Classloader加載了mysql-connector-java.jar的com.mysql.jdbc.Driver。問題是你hard code了必定要加載"com.mysql.jdbc.Driver",不是很優雅,不能實現「用接口編程,自動實例化真的實現「的這種編碼形式。
使用SPI後,代碼大體會這樣
Connection connection = DriverManager.getConnection("jdbc:mysql://xxxxxx/xxx", "xxxx", "xxxxx");
DriverManager就根據"jdbc:mysql"這個提示去找具體實現去了。
而後
System.out.println(connection.getClass().getClassLoader());
就會看到這裏的結果是Application ClassLoader。這就好像Application ClassLoader加載了原本應該由BootstrapClassLoader加載的java.sql.Connection同樣。看起來像是違反了雙親委派模型。但實際上,這裏的Connection的類型其實是「com.mysql.jdbc.JDBC4Connection「,也是個第三方類。AppClassLoader加載一個第三方類看起來並無違反模型。
再進一步調查下Connection接口本身的加載狀況:
System.out.println(java.sql.Connection.class.getClassLoader());
會發現返回的null。說明Connection本身是被Bootstrap ClassLoader加載的。
綜上,並無說Bootstrap ClassLoader加載了個第三方庫或者Application ClassLoader加載了JDK的庫的狀況發生。
因此可否請題主給出具體哪裏寫了「SPI破壞雙親委派模型「?我再仔細看看是否是先後哪裏誰理解錯了。多是我錯了,也多是那個參考錯了。