為什麼需要Class.forName(“com.mysql.jdbc.Driver”)

來源:互聯網
上載者:User

在使用傳統的JDBC串連資料庫的時候,總是需要這一句(以MySQL為例):

Class.forName("com.mysql.jdbc.Driver");   

以前我也沒深究,只是看網上的例子都這麼寫,實際上也跑通了,於是便懶得去管內部原理。不過大概還是清楚的,知道這句話是向DriverManage註冊了一個MySQL的JDBC Driver。

但為什麼要用Class.forName這樣看上去不是很優雅的方式呢?

網上還流傳了一個這樣的版本Class.forName("com.mysql.jdbc.Driver").newInstance(),似乎有點兒多此一舉。

經過實驗,我發現用com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver() 也是可以的,但是只聲明

com.mysql.jdbc.Driver driver = null ,而不執行個體化卻又是不行的。

那麼Driver的註冊到底是在類的初始化時進行的,還是在類的對象初始化時進行的呢? 我也不知道,最好的辦法還是看源碼:

 

package com.mysql.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

// Referenced classes of package com.mysql.jdbc:
//            NonRegisteringDriver

public class Driver extends NonRegisteringDriver
{

    public Driver()
        throws SQLException
    {
    }

    static
    {
        try
        {
            DriverManager.registerDriver(new Driver());
        }
        catch(SQLException E)
        {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

源碼之前沒秘密,com.mysql.jdbc.Driver很簡單,就是紅色的那句,看來是在類的static block裡面做的初始化。

那麼我們只要搞清楚在java裡面,static block執行的時機就可以清楚來龍去脈了。

還是做一個實驗吧:package com.javaye;

class A{
     static{
               System.out.println("Class A loaded");
      }
     public A(){
             System.out.println("create a instance of A");
      }
}


public class Main {
 
      public static void main(String[] args) throws Exception{
                 Class.forName("com.javaye.A");
     }
}
 

列印結果:“Class A loaded”
 

這說明Class.forName可以使類的static block中的代碼得到執行。

然後,我們在修改成下面這樣:

package com.javaye;

class A{
 static{
  System.out.println("Class A loaded");
 }
 public A(){
  System.out.println("create a instance of A");
 }
}
public class Main {
 
 public static void main(String[] args) throws Exception{
  com.javaye.A a = null;
  
 }
}
 

發現沒有列印任何東西,這說明只是聲明某個類的變數,是不會使static block的到執行的。

再改一下:

package com.javaye;

class A{
 static{
  System.out.println("Class A loaded");
 }
 public A(){
  System.out.println("create a instance of A");
 }
}
public class Main {
 
 public static void main(String[] args) throws Exception{
  com.javaye.A a = new com.javaye.A();
  com.javaye.A a2 = new com.javaye.A();
 }
}

輸出結果:

Class A loaded
create a instance of A
create a instance of A
 

這說明執行個體化一個類的話,static block 也會被執行,而且只會被執行一遍。

如果仍有興趣,還可以探索一下Driver的註冊機制:

public static synchronized void registerDriver(java.sql.Driver driver)
 throws SQLException {
 if (!initialized) {
     initialize();
 }
     
 DriverInfo di = new DriverInfo();
 di.driver = driver;
 di.driverClass = driver.getClass();
 di.driverClassName = di.driverClass.getName();
 drivers.addElement(di);    //drivers 是一個vector,儲存著被註冊的driver.
 println("registerDriver: " + di);
 

}

getConnection就是要從drivers裡面挑出一個合適的資料庫driver:

for (int i = 0; i < drivers.size(); i++) {
     DriverInfo di = (DriverInfo)drivers.elementAt(i);
     
     // If the caller does not have permission to load the driver then
     // skip it.
     if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
  println("    skipping: " + di);
  continue;
     }
     try {
  println("    trying " + di);
  Connection result = di.driver.connect(url, info);
  if (result != null) {
      // Success!
      println("getConnection returning " + di);
      return (result);
  }
     } catch (SQLException ex) {
  if (reason == null) {
      reason = ex;
  }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.