您的位置:首页 > 编程语言 > Java开发

JAVA JDBC(MySQL)驱动源码分析(二)

2013-05-31 00:08 387 查看
本文系转载,地址:http://blog.csdn.net/brilliancezhou/article/details/5425687

上一篇中分析了Class.forName(“com.mysql.jdbc.Driver”)幕后所做的事情,也就是在Driver实现类中的静态块和构造函数,本篇主要来分析一下静态块的一句代码:DriverManager.registerDriver方法和其它相关的调用。

    registerDriver方法是一个静态方法,它所要做的工作就是加载所有系统提供的驱动,并把它们添加到具体的类中,形成对象。同时还创建连接,是一个管理驱动的工具类。如果我们使用的是mysql,那么加载的也就是它的驱动。

    此方法的源码如下:

[java] view
plaincopy

public static synchronized void registerDriver(java.sql.Driver driver)  

    throws SQLException {  

    if (!initialized) {  //1  

        initialize();  

    }        

    DriverInfo di = new DriverInfo();  

    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那么它将会进入初始化方法,源码如下:

[java] view
plaincopy

static void initialize() {  

        if (initialized) {  

            return;  

        }  

        initialized = true;  

        loadInitialDrivers();  

        println("JDBC DriverManager initialized");  

    }  

2、Initialize方法中判断initialized值是否为真(其实就是通过此boolean变量判断是否已经初始化完成),之后设置initialized值为true,接着又会调用另一个方法loadInitialDrivers() 同样是静态方法,用于调用系统类装载器,装载所有系统提供的驱动:

loadInitialDrivers()源码:

[java] view
plaincopy

private static void loadInitialDrivers() {  

        String drivers;  

      

        try {  

        drivers = (String) java.security.AccessController.doPrivileged(  

        new sun.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 = new DriverService();  

     // 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) {  

            int x = 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);  

            }  

        }  

    }  

主要代码分析:

    下面这段创建了一个内部类对象,创建此对象时,它会从系统服务中加载驱动

[java] view
plaincopy

DriverService ds = new DriverService();  

DriverService内部类的具体代码:

[java] view
plaincopy

class DriverService implements java.security.PrivilegedAction {  

        Iterator ps = null;  

    public DriverService() {};  

        public Object run() {  

    ps = Service.providers(java.sql.Driver.class);  //从系统服务中加载驱动  

    try {  

           while (ps.hasNext()) { //遍历驱动  

               ps.next();  

           } // end while  

    } catch(Throwable t) {  

        // Do nothing  

    }  

        return null;  

    } //end run  

} //end DriverService  

 

此句代码就是找到所有的拥有权限的java.sql.Driver的实现

[java] view
plaincopy

java.security.AccessController.doPrivileged(ds);  

下面这段,意思是得到系统属性jdbc.drivers对应驱动的驱动名称,使用了JAVA的安全许可

[java] view
plaincopy

drivers = (String) java.security.AccessController.doPrivileged(  

        new sun.security.action.GetPropertyAction("jdbc.drivers"));  

再看看后面的判断和循环

首先判断驱动服务对象是否为null,如果为null则返回,否则进入while循环,这个循环会依次遍历多个数据库驱动,因为jdbc:drivers会有多个数据库驱动,驱动名是以:分割,接下来就是通过Class.forName依次装载驱动类,在其中使用了ClassLoader.getSystemClassLoader()系统类装载器。

[java] view
plaincopy

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程序提供很好的动态特性,有必要去深入理解哦。

接下来再看初始化之后的代码:

[java] view
plaincopy

DriverInfo di = new DriverInfo();  

    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驱动信息类,是一个内部类,

源码如下:

[java] view
plaincopy

class DriverInfo {  

    Driver         driver;  

    Class          driverClass;  

    String         driverClassName;  

    public String toString() {  

    return ("driver[className=" + driverClassName + "," + driver + "]");  

    }  

}  

此类就是添加了三个属性,分别表示驱动对象,驱动的Class对象,以及驱动的类名;同时重写了toString方法。此内部类的作用就是以可以创建DriverInfo对象,以对象的形式保存驱动信息。

接下来就是设置对象的三个属性:

[java] view
plaincopy

DriverInfo di = new DriverInfo();  

di.driver = driver;  

di.driverClass = driver.getClass();  

di.driverClassName = di.driverClass.getName();  

然后添加到集合writeDrivers中,这个集合是Vector类型,定义为DriverManager的属性

writeDrivers定义:

[java] view
plaincopy

private static java.util.Vector writeDrivers = new java.util.Vector();  

驱动添加到集合

[java] view
plaincopy

writeDrivers.addElement(di);  

最后就是调用writeDrivers对象的clone方法

[java] view
plaincopy

readDrivers = (java.util.Vector) writeDrivers.clone();  

readDrivers也是一个类型为Vector的集合,定义为DriverManager的属性

[java] view
plaincopy

private static java.util.Vector readDrivers = new java.util.Vector();  

为什么要先添加到writeDrivers然后再 clone到readDrivers中呢?

writeDrivers和 readDrivers两个都是驱动集合,无论是注册驱动抑或是取消注册,都是先对writeDrivers驱动集合中的数据进行添加或删除,然后再把writeDrivers中的驱动都clone到readDrivers中,每次取出Driver并不是在writeDrivers中,而是在readDrivers中取得。那么这两个驱动集合便可以这样理解,writeDrivers驱动集合负责注册驱动和注销驱动,readDrivers驱动集合负责提供可用的驱动对象,readDrivers中的驱动对象应该都是可用的。把二者分开,使用者就不需加任何判断,很方便。

这里又涉及到一个知识就是clone, 有兴趣的朋友可以查看相关JAVA文档,Thinking in java 中也有详细描述。

这就是初始化的全过程,写了这么多,实际上只做一件事情,就是完成所有驱动的加载。装载之后就是连接了,在连载三当中我会详细描述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JDBC 驱动 MySql