java jdbc(mysql)驱动源码分析_JAVA JDBC(MySQL)驱动源码分析(二)
本文系轉載,地址:http://blog.csdn.net/brilliancezhou/article/details/5425687
上一篇中分析了Class.forName(“com.mysql.jdbc.Driver”)幕后所做的事情,也就是在Driver實現類中的靜態塊和構造函數,本篇主要來分析一下靜態塊的一句代碼:DriverManager.registerDriver方法和其它相關的調用。
registerDriver方法是一個靜態方法,它所要做的工作就是加載所有系統提供的驅動,并把它們添加到具體的類中,形成對象。同時還創建連接,是一個管理驅動的工具類。如果我們使用的是mysql,那么加載的也就是它的驅動。
此方法的源碼如下:
publicstaticsynchronizedvoidregisterDriver(java.sql.Driver?driver)
throwsSQLException?{
if(!initialized)?{//1
initialize();
}
DriverInfo?di?=?newDriverInfo();
di.driver?=?driver;
di.driverClass?=?driver.getClass();
di.driverClassName?=?di.driverClass.getName();
//?Not?Required?--?drivers.addElement(di);
writeDrivers.addElement(di);
println("registerDriver:?"+?di);
/*?update?the?read?copy?of?drivers?vector?*/
readDrivers?=?(java.util.Vector)?writeDrivers.clone();
}
一、初始化操作
1、看看1處的代碼,判斷是否初始化,這個判斷的變量是一個靜態全局boolean值,初始為false
private static boolean initialized = false;
如果此變量的值為false那么它將會進入初始化方法,源碼如下:
staticvoidinitialize()?{
if(initialized)?{
return;
}
initialized?=?true;
loadInitialDrivers();
println("JDBC?DriverManager?initialized");
}
2、Initialize方法中判斷initialized值是否為真(其實就是通過此boolean變量判斷是否已經初始化完成),之后設置initialized值為true,接著又會調用另一個方法loadInitialDrivers() 同樣是靜態方法,用于調用系統類裝載器,裝載所有系統提供的驅動:
loadInitialDrivers()源碼:
privatestaticvoidloadInitialDrivers()?{
String?drivers;
try{
drivers?=?(String)?java.security.AccessController.doPrivileged(
newsun.security.action.GetPropertyAction("jdbc.drivers"));
}?catch(Exception?ex)?{
drivers?=?null;
}
//?If?the?driver?is?packaged?as?a?Service?Provider,
//?load?it.
//?Get?all?the?drivers?through?the?classloader
//?exposed?as?a?java.sql.Driver.class?service.
DriverService?ds?=?newDriverService();
//?Have?all?the?privileges?to?get?all?the
//?implementation?of?java.sql.Driver
java.security.AccessController.doPrivileged(ds);
println("DriverManager.initialize:?jdbc.drivers?=?"+?drivers);
if(drivers?==null)?{
return;
}
while(drivers.length()?!=0)?{
intx?=?drivers.indexOf(':');
String?driver;
if(x?<0)?{
driver?=?drivers;
drivers?=?"";
}?else{
driver?=?drivers.substring(0,?x);
drivers?=?drivers.substring(x+1);
}
if(driver.length()?==0)?{
continue;
}
try{
println("DriverManager.Initialize:?loading?"+?driver);
Class.forName(driver,?true,
ClassLoader.getSystemClassLoader());
}?catch(Exception?ex)?{
println("DriverManager.Initialize:?load?failed:?"+?ex);
}
}
}
主要代碼分析:
下面這段創建了一個內部類對象,創建此對象時,它會從系統服務中加載驅動
DriverService?ds?=newDriverService();
DriverService內部類的具體代碼:
classDriverServiceimplementsjava.security.PrivilegedAction?{
Iterator?ps?=?null;
publicDriverService()?{};
publicObject?run()?{
ps?=?Service.providers(java.sql.Driver.class);//從系統服務中加載驅動
try{
while(ps.hasNext())?{//遍歷驅動
ps.next();
}?//?end?while
}?catch(Throwable?t)?{
//?Do?nothing
}
returnnull;
}?//end?run
}?//end?DriverService
此句代碼就是找到所有的擁有權限的java.sql.Driver的實現
java.security.AccessController.doPrivileged(ds);
下面這段,意思是得到系統屬性jdbc.drivers對應驅動的驅動名稱,使用了JAVA的安全許可
drivers?=?(String)?java.security.AccessController.doPrivileged(
newsun.security.action.GetPropertyAction("jdbc.drivers"));
再看看后面的判斷和循環
首先判斷驅動服務對象是否為null,如果為null則返回,否則進入while循環,這個循環會依次遍歷多個數據庫驅動,因為jdbc:drivers會有多個數據庫驅動,驅動名是以:分割,接下來就是通過Class.forName依次裝載驅動類,在其中使用了ClassLoader.getSystemClassLoader()系統類裝載器。
if(drivers?==null)?{
return;
}
while(drivers.length()?!=0)?{
…
Class.forName(driver,?true,?ClassLoader.getSystemClassLoader());
…
}
上面分析的就是在registerDriver方法中所要做的第一件事情:初始化。可以看到initialize()做的工作就是裝載驅動,同時還需要使用到系統的一些功能。如: java.security.AccessController.doPrivileged,此方法允許在一個類實例中的代碼通知這個AccessController,它的代碼主體享受特權(Privileged),它不管這個請求是由什么代碼所引發的,只是單獨負責對它可得到的資源的訪問請求。比如說,一個調用者在調用doPrivileged方法時,可被標識為特權。AccessController做訪問控制決策時,如果checkPermission方法遇到一個通過doPrivileged方法調用而被視為特權調用者,那么checkPermission方法不會作許可檢查,表示那個訪問請求是被允許的,如果調用者沒有許可,則會拋出一個異常。
如:ClassLoader.getSystemClassLoader(),java中所有類都是通過ClassLoader裝載的,ClassLoader可以為java程序提供很好的動態特性,有必要去深入理解哦。
接下來再看初始化之后的代碼:
DriverInfo?di?=newDriverInfo();
di.driver?=?driver;
di.driverClass?=?driver.getClass();
di.driverClassName?=?di.driverClass.getName();
//?Not?Required?--?drivers.addElement(di);
writeDrivers.addElement(di);
println("registerDriver:?"+?di);
/*?update?the?read?copy?of?drivers?vector?*/
readDrivers?=?(java.util.Vector)?writeDrivers.clone();
創建DriverInfo對象
DriverInfo di = new DriverInfo();
DriverInfo驅動信息類,是一個內部類,
源碼如下:
classDriverInfo?{
Driver?????????driver;
Class??????????driverClass;
String?????????driverClassName;
publicString?toString()?{
return("driver[className="+?driverClassName?+","+?driver?+"]");
}
}
此類就是添加了三個屬性,分別表示驅動對象,驅動的Class對象,以及驅動的類名;同時重寫了toString方法。此內部類的作用就是以可以創建DriverInfo對象,以對象的形式保存驅動信息。
接下來就是設置對象的三個屬性:
DriverInfo?di?=newDriverInfo();
di.driver?=?driver;
di.driverClass?=?driver.getClass();
di.driverClassName?=?di.driverClass.getName();
然后添加到集合writeDrivers中,這個集合是Vector類型,定義為DriverManager的屬性
writeDrivers定義:
privatestaticjava.util.Vector?writeDrivers?=newjava.util.Vector();
驅動添加到集合
writeDrivers.addElement(di);
最后就是調用writeDrivers對象的clone方法
readDrivers?=?(java.util.Vector)?writeDrivers.clone();
readDrivers也是一個類型為Vector的集合,定義為DriverManager的屬性
privatestaticjava.util.Vector?readDrivers?=newjava.util.Vector();
為什么要先添加到writeDrivers然后再 clone到readDrivers中呢? writeDrivers和 readDrivers兩個都是驅動集合,無論是注冊驅動抑或是取消注冊,都是先對writeDrivers驅動集合中的數據進行添加或刪除,然后再把writeDrivers中的驅動都clone到readDrivers中,每次取出Driver并不是在writeDrivers中,而是在readDrivers中取得。那么這兩個驅動集合便可以這樣理解,writeDrivers驅動集合負責注冊驅動和注銷驅動,readDrivers驅動集合負責提供可用的驅動對象,readDrivers中的驅動對象應該都是可用的。把二者分開,使用者就不需加任何判斷,很方便。 這里又涉及到一個知識就是clone, 有興趣的朋友可以查看相關JAVA文檔,Thinking in java 中也有詳細描述。 這就是初始化的全過程,寫了這么多,實際上只做一件事情,就是完成所有驅動的加載。裝載之后就是連接了,在連載三當中我會詳細描述。
總結
以上是生活随笔為你收集整理的java jdbc(mysql)驱动源码分析_JAVA JDBC(MySQL)驱动源码分析(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云计算呼叫中心_干货|云呼叫中心系统和传
- 下一篇: 椭圆形中间一个大写的v_静安区椭圆形桥梁