JDBC自動加載驅動的SPI機制


 

本人試驗無意間發現,只要前面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包來實現擴展功能的熱插拔。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM