天天看點

根據class擷取值_面試題:Class.forName加載驅動的目的,不用這種方式可以嗎?

本篇主要是分析建立資料庫連接配接時的Class.forName的作用以及其替代方法。

下面是擷取資料庫連接配接的通用寫法:

Class.forName(driver);Connection conn = DriverManager.getConnection(url, username, password);
           

不過在解釋具體原因之前先簡單了解Class.forName的作用。

現在假設一個類還沒有被裝進記憶體,Class.forName(String className)這個方法會做以下幾件事情:

1、裝載。将位元組碼讀入記憶體,并産生一個與之對應的java.lang.Class類對象2、連接配接。這一步會驗證位元組碼,為static變量配置設定記憶體,并賦預設值(0或null)(注意:執行個體變量這裡不會配置設定記憶體)。比如:public static int a = 1;這一步過後a的值為0而不是1.3、初始化。執行類變量的指派動作和靜态代碼塊。即為類的static變量賦初始值,那麼上面這個将a指派為1的操作就是這個時候做的。除此之外,還要調用類的static塊(這一步是關鍵)。這裡隻是簡單描述一下過程,其實jvm做的事遠比這些複雜得多。
           
根據class擷取值_面試題:Class.forName加載驅動的目的,不用這種方式可以嗎?

根據上面的分析,猜測driver類中應該有靜态代碼塊執行某些操作,讓我們進入到driver類看下裡面有沒有static塊,這裡以com.mysql.jdbc.Driver為例:

根據class擷取值_面試題:Class.forName加載驅動的目的,不用這種方式可以嗎?

從上面的代碼可以看到這一句: java.sql.DriverManager.registerDriver(new Driver());

DriverManager類是用來管理資料庫中的所有驅動程式的,是JDBC的管理層,作用于使用者和驅動程式之間,跟蹤可用的驅動程式,并在資料庫的驅動程式之間建立連接配接。此外,DriverManager類中的方法都是靜态方法,是以在程式中無須對它進行執行個體化,直接通過類名就可以調用
           

那我們是不是可以用DriverManager.registerDriver來替代Class.forName,測試一下發現能擷取到連接配接:

根據class擷取值_面試題:Class.forName加載驅動的目的,不用這種方式可以嗎?

即然如此按照上面的分析我們也可以直接new Driver();如下也是可以擷取到連接配接的

根據class擷取值_面試題:Class.forName加載驅動的目的,不用這種方式可以嗎?

不過我們還是推薦使用Class.forName,因為DriverManager.registerDriver和new Driver都會多建立了一個driver執行個體。

另:從jdk1.6開始提供spi機制,對于驅動包下含有/META-INF/services/java.sql.Driver檔案的包,可以不用顯式的調用Class.forName加載驅動了,調用DriverManager.getConnection時會通過spi機制加載合适的驅動。

這個讀者朋友們可以自己嘗試下。