本人試驗無意間發現,只要前面pom引入了mysql-connector-java這個包,什么都不寫也會加載mysql數據庫驅動, (當然如果不引入mysql-connector-java這個包是不行的)這是為什么呢?
一 為什么java不加載驅動可以
源碼包里DriverManager類上面說明了,不加載也可以的注釋。
* <P>Applications no longer need to explicitly load JDBC drivers using <code>Class.forName()</code>. Existing programs * which currently load JDBC drivers using <code>Class.forName()</code> will continue to work without * modification.
翻譯過來:
* <P>應用程序不再需要使用<code> Class.forName()</ code>顯式加載JDBC驅動程序。 現有程序
* 當前使用<code> Class.forName()</ code>加載JDBC驅動程序將繼續工作而無需
* 修改。
原來在新版本的JDBC中不用在通過Class.forName()來顯示加載JDBC驅動,那到底是怎么實現的呢,我們來看下源碼。
二 源碼分析
下面是引入的mysql-connector-java包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
public static void insertData() { private String URL = "jdbc:mysql://localhost:port/databaseName?useUnicode=true&characterEncoding=UTF-8"; private String USER = "xx"; private String PASSWORD = "xx"; //1 加載數據庫驅動 Connection connection = DriverManager.getConnection(URL,USER,PASSWORD); // 2 獲取鏈接connection PreparedStatement preparedStatement = connection.prepareStatement("insert into test (name, sex) values (?,?)"); // 3 通過statement對象執行sql preparedStatement.setString(1, "xx"); preparedStatement.setString(2, "yy"); Boolean result = preparedStatement.execute(); // 4 獲取返回結果 }
啟動服務后,執行靜態方法DriverManager.getConnection 因為需要加載DriverManager類,所以執行static靜態代碼塊。



在java這頭定義了一個Driver接口,ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class),那么ServiceLoader.load()方法是干什么的呢?
在ServiceLoader.load時,根據傳入的接口類,遍歷META-INF/services目錄下的以該類命名的文件中的所有類,並實例化返回。ServiceLoader是spi機制的一個實現
具體可以參加ServiceLoader類的源代碼如下圖,PREIX是META-INF/services,service.getName是接口Driver的類名稱,拼接出文件路徑:

拼出的全路徑fullName是:META-INF/services/java.sql.Driver,然后去本地找到該路徑下的這個文件,然后把這個文件加載進來,這個文件的內容如下

文件內容是:com.mysql.cj.jdbc.Driver,這個類就是mysql廠商提供的驅動里面的Driver實現類,然后對其進行初始化加載,進行實例化,調這個類的static靜態塊,執行注冊驅動。

三 SPI機制總結
ServiceLoader是SPI的是一種實現,SPI,全稱Service Provider Interface,用於一些服務提供給第三方實現或者擴展,可以增強框架的擴展或者替換一些組件。 通過jar包來實現擴展功能的熱插拔。
