本文系转载,地址: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 中也有详细描述。 这就是初始化的全过程,写了这么多,实际上只做一件事情,就是完成所有驱动的加载。装载之后就是连接了,在连载三当中我会详细描述。