关于jdbc的源码解析 DriverManager 和 Driver的加载

注: 本系列文章使用JDK1.5 数据库驱动版本 mysql-connector-java-5.1.8b

 

上一篇中分析了Class.forName(“com.mysql.jdbc.Driver”)幕后所做的事情,也就是在Driver实现类中的静态块和构造函数,本篇主要来分析一下静态块的一句代码:DriverManager.registerDriver方法和其它相关的调用。
    registerDriver方法是一个静态方法,它所要做的工作就是加载所有系统提供的驱动,并把它们添加到具体的类中,形成对象。同时还创建连接,是一个管理驱动的工具类。如果我们使用的是mysql,那么加载的也就是它的驱动。
    此方法的源码如下:

  1. public static synchronized void registerDriver(java.sql.Driver driver)  
  2.     throws SQLException {  
  3.     if (!initialized) {  //1  
  4.         initialize();  
  5.     }        
  6.     DriverInfo di = new DriverInfo();  
  7.     di.driver = driver;  
  8.     di.driverClass = driver.getClass();  
  9.     di.driverClassName = di.driverClass.getName();  
  10.     // Not Required -- drivers.addElement(di);  
  11.     writeDrivers.addElement(di);   
  12.     println("registerDriver: " + di);  
  13.     /* update the read copy of drivers vector */  
  14.     readDrivers = (java.util.Vector) writeDrivers.clone();  
  15. }  

一、初始化操作
1、看看1处的代码,判断是否初始化,这个判断的变量是一个静态全局boolean值,初始为false
    private static boolean initialized = false;


如果此变量的值为false那么它将会进入初始化方法,源码如下:

  1. static void initialize() {  
  2.         if (initialized) {  
  3.             return;  
  4.         }  
  5.         initialized = true;  
  6.         loadInitialDrivers();  
  7.         println("JDBC DriverManager initialized");  
  8.     }  

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

  1. private static void loadInitialDrivers() {  
  2.         String drivers;  
  3.       
  4.         try {  
  5.         drivers = (String) java.security.AccessController.doPrivileged(  
  6.         new sun.security.action.GetPropertyAction("jdbc.drivers"));  
  7.         } catch (Exception ex) {  
  8.             drivers = null;  
  9.         }  
  10.           
  11.         // If the driver is packaged as a Service Provider,  
  12.         // load it.  
  13.         // Get all the drivers through the classloader   
  14.         // exposed as a java.sql.Driver.class service.  
  15.       
  16.      DriverService ds = new DriverService();  
  17.      // Have all the privileges to get all the   
  18.      // implementation of java.sql.Driver  
  19.      java.security.AccessController.doPrivileged(ds);  
  20.          println("DriverManager.initialize: jdbc.drivers = " + drivers);  
  21.         if (drivers == null) {  
  22.             return;  
  23.         }  
  24.         while (drivers.length() != 0) {  
  25.             int x = drivers.indexOf(':');  
  26.             String driver;  
  27.             if (x < 0) {  
  28.                 driver = drivers;  
  29.                 drivers = "";  
  30.             } else {  
  31.                 driver = drivers.substring(0, x);  
  32.                 drivers = drivers.substring(x+1);  
  33.             }  
  34.             if (driver.length() == 0) {  
  35.                 continue;  
  36.             }  
  37.             try {  
  38.                 println("DriverManager.Initialize: loading " + driver);  
  39.                 Class.forName(driver, true,  
  40.                   ClassLoader.getSystemClassLoader());  
  41.             } catch (Exception ex) {  
  42.                 println("DriverManager.Initialize: load failed: " + ex);  
  43.             }  
  44.         }  
  45.     }  

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

  1. DriverService ds = new DriverService();  

DriverService内部类的具体代码:

  1. class DriverService implements java.security.PrivilegedAction {  
  2.         Iterator ps = null;  
  3.     public DriverService() {};  
  4.         public Object run() {  
  5.     ps = Service.providers(java.sql.Driver.class);  //从系统服务中加载驱动  
  6.     try {  
  7.            while (ps.hasNext()) { //遍历驱动  
  8.                ps.next();  
  9.            } // end while  
  10.     } catch(Throwable t) {  
  11.         // Do nothing  
  12.     }  
  13.         return null;  
  14.     } //end run  
  15. //end DriverService  

 

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

  1. java.security.AccessController.doPrivileged(ds);  

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

  1. drivers = (String) java.security.AccessController.doPrivileged(  
  2.         new sun.security.action.GetPropertyAction("jdbc.drivers"));  

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

  1. if (drivers == null) {  
  2.             return;  
  3.         }  
  4.  while (drivers.length() != 0) {  
  5. …  
  6. Class.forName(driver, true, ClassLoader.getSystemClassLoader());  
  7. …  
  8. }  

上面分析的就是在registerDriver方法中所要做的第一件事情:初始化。可以看到initialize()做的工作就是装载驱动,同时还需要使用到系统的一些功能。如: java.security.AccessController.doPrivileged,此方法允许在一个类实例中的代码通知这个AccessController,它的代码主体享受特权(Privileged),它不管这个请求是由什么代码所引发的,只是单独负责对它可得到的资源的访问请求。比如说,一个调用者在调用doPrivileged方法时,可被标识为特权。AccessController做访问控制决策时,如果checkPermission方法遇到一个通过doPrivileged方法调用而被视为特权调用者,那么checkPermission方法不会作许可检查,表示那个访问请求是被允许的,如果调用者没有许可,则会抛出一个异常。

如:ClassLoader.getSystemClassLoader(),java中所有类都是通过ClassLoader装载的,ClassLoader可以为java程序提供很好的动态特性,有必要去深入理解哦。

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

  1. DriverInfo di = new DriverInfo();  
  2.     di.driver = driver;  
  3.     di.driverClass = driver.getClass();  
  4.     di.driverClassName = di.driverClass.getName();  
  5.     // Not Required -- drivers.addElement(di);  
  6.     writeDrivers.addElement(di);   
  7.     println("registerDriver: " + di);  
  8.     /* update the read copy of drivers vector */  
  9.     readDrivers = (java.util.Vector) writeDrivers.clone();  

创建DriverInfo对象
DriverInfo di = new DriverInfo();
DriverInfo驱动信息类,是一个内部类,
源码如下:

  1. class DriverInfo {  
  2.     Driver         driver;  
  3.     Class          driverClass;  
  4.     String         driverClassName;  
  5.     public String toString() {  
  6.     return ("driver[className=" + driverClassName + "," + driver + "]");  
  7.     }  
  8. }  

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

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

  1. DriverInfo di = new DriverInfo();  
  2. di.driver = driver;  
  3. di.driverClass = driver.getClass();  
  4. di.driverClassName = di.driverClass.getName();  

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

writeDrivers定义:

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

驱动添加到集合

  1. writeDrivers.addElement(di);  

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

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


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

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

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值