使用JDBC時,我們都會很自然得使用下列語句:
- Class.forName( "com.mysql.jdbc.Driver" );
- String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8" ;
- String user = "" ;
- String psw = "" ;
- Connection con = DriverManager.getConnection(url,user,psw);
爲什麼說很自然呢,因爲無論是網上還是書本教程上得例子都是這樣的,而且程序也確實正常運行了,於是大家也就心安理得的找葫蘆畫瓢下去了。
一定要有這一句嗎?不是的,我們完全可以用這樣一句代替它:
- com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
- //or:
- //new com.mysql.jdbc.Driver();
- String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8" ;
- String user = "" ;
- String psw = "" ;
- Connection con = DriverManager.getConnection(url,user,psw);
大家可能都看出個大概來了,我們只需要在調用DriverManager的getConnection方法之前,保證相應的Driver類已經被加載到 jvm中,並且完成了類的初始化工作就行了,而具體是怎樣實現這個功能卻是沒有講究的。上面兩種方法都可以實現這個功能,因此程序可以正常運行。注意了, 如果我們進行如下操作,程序是不能正常運行的,因爲這樣僅僅使Driver類被裝載到jvm中,卻沒有進行相應的初始化工作。
- com.mysql.jdbc.Driver driver = null ;
- //or:
- ClassLoader cl = new ClassLoader();
- cl.loadClass( "com.mysql.jdbc.Driver" );
我們都知道JDBC是使用Bridge模式進行設計的,DriverManager就是其中的Abstraction,java.sql.Driver是
Implementor,com.mysql.jdbc.Driver是Implementor的一個具體實現(請參考GOF的Bridge模式的描
述)。大家注意了,前一個Driver是一個接口,後者卻是一個類,它實現了前面的Driver接口。
Bridge模式中,Abstraction(DriverManager)是要擁有一個Implementor(Driver)的引用的,但是我們在使
用過程中,並沒有將Driver對象註冊到DriverManager中去啊,這是怎麼回事呢?jdk文檔對Driver的描述中有這麼一句:
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager
哦,原來是com.mysql.jdbc.Driver在裝載完後自動幫我們完成了這一步驟。源代碼是這樣的:
- package com.mysql.jdbc
- public class Driver extends NonRegisteringDriver implements java.sql.Driver {
- // ~ Static fields/initializers
- // --------------------------------------------- //
- // Register ourselves with the DriverManager
- //
- static {
- t ry {
- java.sql.DriverManager.registerDriver( new Driver());
- } catch (SQLException E) {
- throw new RuntimeException( "Can't register driver!" );
- }
- }
- // ~ Constructors
- // -----------------------------------------------------------
- /**
- * Construct a new driver and register it with DriverManager
- *
- * @throws SQLException
- * if a database error occurs.
- */
- public Driver() throws SQLException {
- // Required for Class.forName().newInstance()
- }
- }
- 這裏ClassLoader爲什麼不行,是類加載器的機制決定的 www.javaeye.com/topic/25053
static塊在什麼時候執行?
1)當調用forName(String)載入class時執行,如果調用ClassLoader.loadClass並不會執行.forName(String,false,ClassLoader)時也不會執行.
2)如果載入Class時沒有執行static塊則在第一次實例化時執行.比如new ,Class.newInstance()操作
3)static塊僅執行一次