Class.forName解析以及使用
2019獨角獸企業重金招聘Python工程師標準>>>
這個類在剛學習Java連接數據庫的時候見到這個這種寫法,并且工作這么多年,也許是接觸的東西比較少,這種用法也就只有在自己手寫數據庫連接代碼的時候見過,在其他的時候還真是沒見過。
在Class類中,對此方法有如下聲明
方法重載了三次。
查看第一個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());} }運行以上代碼,輸出的結果是:
也就是ReflectionCaller這個類對象。這個方法還是比較有趣的,如果在以后我們自己寫代碼的時候,想知道誰在調用我這些的這些方法,就可以跟蹤出來了。
獲取調用者信息以后,會調用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中強烈建議,每個驅動程序類應該盡可能的小和獨立,這樣在加載和查詢驅動類的時候,才不會引入大量的支持代碼。
?
轉載于:https://my.oschina.net/u/2457218/blog/818082
總結
以上是生活随笔為你收集整理的Class.forName解析以及使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现学现卖微信小程序开发(二)
- 下一篇: linux安装部署apache+subv