JDBC學習2:為什么要寫Class.forName("XXX")?


Class.forName(String name)

接上一篇JDBC。本來這個內容是放在前面的一篇里面的一起的,后來發現越寫越多,想想看就算了,還是單獨開一篇文章好了,這樣也能寫得更加詳細點。

上一篇文章的第4點,getConnection()方法里面,我把從.properties里面獲取mysqlpackage的地方替換成實際的value值,那么替換后的應該是Class.forName("com.mysql.jdbc.Driver"),實際上所有的JDBC連接先寫的基本上也都是這一句。另外,哪怕刪除這一句,也是可以運行成功的。那為什么還要Class.forName("com.mysql.jdbc.Driver")呢?OK,分點講解。

 

為什么要Class.forName("com.mysql.jdbc.Driver")?

JDBC是23種模式中的橋接模式的典型應用,熟悉橋接模式的基本上稍微看一下源代碼就知道為什么了,那橋接模式這里不講,只講為什么要這么做。Class.forName(String className)的作用有兩個,第一是CLASSPATH下指定名字的.class文件加載到Java虛擬機內存中, 第二是初始化這個類。看到這句話,返回值都沒有,那寫在這里的作用很明顯了,就是初始化"com.mysql.jdbc.Drvier"。初始化做了什么?給靜態資源賦值以及執行靜態代碼塊,所以,反編譯一下"mysql-connector-java-5.1.20-bin.jar"這個jar包,查看一下Driver類:

public class Driver extends NonRegisteringDriver
  implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } }

看到Class.forName("com.mysql.jdbc.Driver")的作用實際上就是調用DriverManager的registerDriver方法注冊一個mysql的JDBC驅動(Driver)而已,Driver繼承NonRegisteringDriver.java,NonRegisteringDriver.java實現了JDK提供的Driver接口,這個Driver提供了若干數據庫連接的方法,每個不同的數據庫連接類都必須實現它,並重寫和具體的數據庫連接的算法。DriverManager也是JDK中的類,截一些關鍵代碼:

private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList();
public static synchronized void registerDriver(Driver paramDriver)
    throws SQLException
  {
    if (paramDriver != null)
      registeredDrivers.addIfAbsent(new DriverInfo(paramDriver));
    else
      throw new NullPointerException();
    println("registerDriver: " + paramDriver);
  }

底層利用了一個CopyOnWriteArrayList作為容器(這是一個線程安全的容器,不過每次add的時候都會對底層數組進行一次新的復制,所以在讀遠多於寫的時候建議可以使用這個),放那些注冊進去的DriverInfo。最終getConnection(...)的時候就拿registerDrivers里面注冊進去的具體的某個數據庫的DriverInfo(像MySql的Driver就在DriverInfo里面)去連接具體的數據庫。OK,所以總結一下整個流程:

JDK不負責和數據庫連接打交道,也沒必要,只提供一個具體的接口Driver,告訴所有第三方,要連接數據庫,就去實現這個接口,然后通過DriverManager注冊一下,到時候連接某個數據庫的時候,你已經在我這里注冊了,我會調用你注冊進來的Driver里面的方法去對指定數據庫進行連接的。然后Mysql就實現自己的Driver,Oracle就實現自己的Driver,通過static塊注冊一下,再然后,就沒有然后了。

 

為什么不直接new?

意思是這么寫"com.mysql.jdbc.Driver d = new com.mysql.jdbc.Driver();",可以啊,因為在new的時候會自動觸發對一個類的初始化。問題是new出來干嘛?com.mysql.jdbc.Driver里面的方法我們會用到嗎,並且我們知道怎么用嗎?僅僅為了初始化一個類而new一個類實例出來還不如不去new,直接使用Class.forName(String name)初始化就可以了。DriverManager類的getConnection(...)方法的存在本身就是幫助用戶調用Driver里面的各種方法連接數據庫,JDK都做好了,開發者就沒必要自己寫了。

 

為什么刪除Class.forName("com.mysql.jdbc.Driver")還是可以運行?

1996年1月23日JDK1.0發布,Java語言有了第一個正式版本的運行環境。JDBC是1997年2月19日,在JDK1.1的版本中發布的,從版本就看得出,JDBC屬於Java技術的一些最基礎的功能點。那在JDK1.5之后,其實已經不需要去顯式調用Class.forName("com.mysql.jdbc.Driver")了,DriverManager會自動去加載合適的驅動,但是前提是CLASSPATH下必須有驅動jar包


免責聲明!

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



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