這個類在剛學習Java鏈接數據庫的時候見到這個這種寫法,而且工做這麼多年,也許是接觸的東西比較少,這種用法也就只有在本身手寫數據庫鏈接代碼的時候見過,在其餘的時候還真是沒見過。java
在Class類中,對此方法有以下聲明mysql
方法重載了三次。sql
查看第一個forName方法的聲明爲:數據庫
@CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }
首先在這個方法中,使用到了Reflection.getCallerClass(),返回是調用者對象框架
針對getCallerClass這個方法,這個方法是native的,聲明以下:函數
@CallerSensitive public static native Class getCallerClass();
因爲是native方法,就暫時不跟進去了,這個方法的意思返回調用者 (class對象),也就是說是誰調用調用了我這個類的方法。以下示例:學習
public class ReflectionCaller { public static void main(String[] args) { InnerClass i = new InnerClass(); i.innerMethod(); } } class InnerClass { public void innerMethod() { System.out.println(Reflection.getCallerClass()); } }
運行以上代碼,輸出的結果是:ui
也就是ReflectionCaller這個類對象。這個方法仍是比較有趣的,若是在之後咱們本身寫代碼的時候,想知道誰在調用我這些的這些方法,就能夠跟蹤出來了。spa
獲取調用者信息之後,會調用Class.forname0方法,進行加載和初始化類。看到forname0這個方法又是一個native方法。線程
private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller) throws ClassNotFoundException;
這個方法的做用是根據name加載傳遞過來的類,而且根據initialize來決定是否要進行初始化,所謂初始化指的是加載裏面的靜態塊之類的。加載的時候採用caller相同的類加載器記性加載。
從中能夠看出Class.forName和Classloader.lodeclass的區別是什麼,Class.forName能夠加載類而且控制是否要對類進行初始化,而ClassLoader.loadClass只對類進行加載,不進行初始化。
知道了Class.forName 的做用,那接下來就看一下針對鏈接mysql的具體問題。
根據第一節,能夠看到鏈接字符串爲:
Class.forName("com.mysql.jdbc.Driver");
也就是說會加載com.mysql.jdbc.Driver這個類,而且進行初始化。找到mysql-connector-java.jar的源碼,這個類很是簡單。
public class Driver extends NonRegisteringDriver implements java.sql.Driver { // // Register ourselves with the DriverManager // static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } /** * 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() } }
這個類中 就一個靜態塊和一個無參的構造函數,經過靜態塊的內容能夠看出,實例了的一個Driver,而後註冊到DriverManager,DriverManager把這個Driver存儲到了一個CopyOnWriteArrayList中。
同時Driver還繼承了AbandonedConnectionCleanupThread這個類,這個類繼承Thread,啓動一個守護線程,而後清理廢棄的類對象。
以上就是咱們在鏈接mysql時,Class.forName的功能。可是須要注意的是 Java 的SQL框架容許多個數據庫的Driver,每個Driver都要實現java.sql.Driver接口,針對給出來的鏈接數據庫的請求,DriverManager嘗試去load儘量多的它找到的drivers,而後根據這些driver嘗試使用給出來的數據庫鏈接字符串去嘗試鏈接數據庫。 在mysql的NonRegisteringDriver中強烈建議,每一個驅動程序類應該儘量的小和獨立,這樣在加載和查詢驅動類的時候,纔不會引入大量的支持代碼。