關於Class.forName(“com.mysql.jdbc.Driver”)
傳統的使用jdbc來訪問數據庫的流程為:
Class.forName(“com.mysql.jdbc.Driver”);
String url = “jdbc:mysql://localhost:3306/test?user=root&password=123456″;
Connection con = DriverManager.getConnection(url);
Statement statement = con.createStatement();
最開始使用的時候,不明白為什麽首先要加載一個驅動類,之後就可以取得了Connection了,很好奇DriverManager是怎麽獲得那個驅動類的信息,後來看了下com.mysql.jdbc.Driver這個類的源代碼,豁然開朗了。原來在com.mysql.jdbc.Driver類中有這麽一段靜態初始化代碼:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException(“Can’t register driver!”);
}
}
也就是,在Class.forName加載完驅動類,開始執行靜態初始化代碼時,會自動新建一個Driver的對象,並調用DriverManager.registerDriver把自己註冊到DriverManager中去。
ps1:
Class.forName(String): 加載類,並且執行類初始化;可以通過Class.forName(String, boolean, ClassLoader)第二個參數來僅僅加載類不執行初始化;
ClassLoader.loadClass(String): 僅僅加載類,不執行類初始化;
ps2: 有時會看到這種用法:
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
這是沒有必要的,正如前述,靜態初始化已經new了一個Driver的對象,註冊到DriverManager中去,在此再建立一個Driver對象則是完全沒有必要的,浪費空間。
ps3: 結合ps1,Class.forName(“com.mysql.jdbc.Driver”);相當於:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class cls = loader.loadClass(“com.mysql.jdbc.Driver”);
cls.newInstance();
這種方法的問題同ps2, 浪費了一個Driver對象;
ps4: 在java 6中,引入了service provider的概念,即可以在配置文件中配置service(可能是一個interface或者abstract class)的provider(即service的實現類)。配置路徑是:/META-INF/services/下面。詳細信息見:http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
而java.sql.DriverManager也添加了對此的支持,因此,在JDK6中,DriverManager的查找Driver的範圍為:
1)system property “jdbc.drivers” 中配置的Driver值;
2)用戶調用Class.forName()註冊的Driver
3)service provider配置文件java.sql.Driver中配置的Driver值。
因此,在jdk6中,其實是可以不用調用Class.forName來加載mysql驅動的,因為mysql的驅動程序jar包中已經包含了java.sql.Driver配置文件,並在文件中添加了com.mysql.jdbc.Driver.但在JDK6之前版本,還是要調用這個方法。
參考文檔:
1)http://docs.oracle.com/javase/1.5.0/docs/api/java/sql/DriverManager.html
2)http://docs.oracle.com/javase/6/docs/api/index.html?java/sql/DriverManager.html
3)http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
關於Class.forName(“com.mysql.jdbc.Driver”)