JDBC驱动加载原理全面解析

Posted 亮亮-AC米兰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC驱动加载原理全面解析相关的知识,希望对你有一定的参考价值。

本文转载自http://blog.csdn.net/luanlouis/article/details/29850811,感谢分享

前言

         最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解。所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者一个参考~~~以下是本文的组织结构,读者可以点击上面的目录查看:


概述       

      一般情况下,在应用程序中进行数据库连接,调用JDBC接口,首先要将特定厂商的JDBC驱动实现加载到系统内存中,然后供系统使用。基本结构图如下:

    

驱动加载入内存的过程

    这里所谓的驱动,其实就是实现了java.sql.Driver接口的类。如oracle的驱动类是 oracle.jdbc.driver.OracleDriver.class(此类可以在oracle提供的JDBC jar包中找到),此类实现了java.sql.Driver接口。

由于驱动本质上还是一个class,将驱动加载到内存和加载普通的class原理是一样的:使用Class.forName("driverName")。以下是将常用的数据库驱动加载到内存中的代码:

[java]  view plain  copy  print ?
  1. //加载Oracle数据库驱动  
  2. Class.forName("oracle.jdbc.driver.OracleDriver");  
  3.   
  4. //加载SQL Server数据库驱动  
  5. Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");  
  6.   
  7. //加载mysql 数据库驱动  
  8. Class.forName("com.mysql.jdbc.Driver");  

         注意:Class.forName()将对应的驱动类加载到内存中,然后执行内存中的static静态代码段,代码段中,会创建一个驱动Driver的实例,放入DriverManager中,供DriverManager使用。

      例如,在使用Class.forName() 加载oracle的驱动oracle.jdbc.driver.OracleDriver时,会执行OracleDriver中的静态代码段,创建一个OracleDriver实例,然后调用DriverManager.registerDriver()注册:

[java]  view plain  copy  print ?
  1. static   
  2.     Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");  
  3.     try   
  4.         if (defaultDriver == null)   
  5.             //创建一个OracleDriver实例,然后注册到DriverManager中  
  6.                                defaultDriver = new OracleDriver();  
  7.             DriverManager.registerDriver(defaultDriver);  
  8.           
  9.   
  10.      catch (RuntimeException localRuntimeException)   
  11.      catch (SQLException localSQLException)   
  12.       


Driver的功能

      java.sql.Driver接口规定了Driver应该具有以下功能:


其中:

acceptsURL(String url) 方法用来测试对指定的url,该驱动能否打开这个url连接。driver对自己能够连接的url会制定自己的协议,只有符合自己的协议形式的url才认为自己能够打开这个url,如果能够打开,返回true,反之,返回false;

例如:oracle定义的自己的url协议如下:

jdbc:oracle:thin:@//<host>:<port>/ServiceName

jdbc:oracle:thin:@<host>:<port>:<SID>

oracle自己的acceptsURL(String url)方法如下:

[java]  view plain  copy  print ?
  1. public boolean acceptsURL(String paramString)   
  2.     if (paramString.startsWith("jdbc:oracle:"))   
  3.         return (oracleDriverExtensionTypeFromURL(paramString) > -2);  
  4.       
  5.   
  6.     return false;  
  7.   
  8.   
  9. private int oracleDriverExtensionTypeFromURL(String paramString)   
  10.     int i = paramString.indexOf(58) + 1;  
  11.   
  12.     if (i == 0)   
  13.         return -2;  
  14.       
  15.     int j = paramString.indexOf(58, i);  
  16.   
  17.     if (j == -1)   
  18.         return -2;  
  19.       
  20.     if (!(paramString.regionMatches(true, i, "oracle"0, j - i)))   
  21.         return -2;  
  22.       
  23.     ++j;  
  24.   
  25.     int k = paramString.indexOf(58, j);  
  26.   
  27.     if (k == -1)   
  28.         return -3;  
  29.       
  30.     String str = paramString.substring(j, k);  
  31.   
  32.     if (str.equals("thin"))   
  33.         return 0;  
  34.       
  35.     if ((str.equals("oci8")) || (str.equals("oci")))   
  36.         return 2;  
  37.       
  38.   
  39.     return -3;  
  40.   

     由上可知oracle定义了自己应该接收什么类型的URL,自己能打开什么类型的URL连接(注意:这里acceptsURL(url)只会校验url是否符合协议,不会尝试连接判断url是否有效) 。拓展阅读:常用数据库 JDBC URL格式

connect(String url,Properties info)方法,创建Connection对象,用来和数据库的数据操作和交互,而Connection则是真正数据库操作的开始(在此方法中,没有规定是否要进行acceptsURL()进行校验)。

手动加载驱动 Driver 并实例化进行数据库操作的例子

[java]  view plain  copy  print ?
  1. public static void driverTest()  
  2.     try   
  3.         //1.加载oracle驱动类,并实例化  
  4.         Driver driver = (Driver) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
  5.   
  6.         //2.判定指定的URL oracle驱动能否接受(符合oracle协议规则)  
  7.         boolean flag = driver.acceptsURL("jdbc:oracle:thin:@127.0.0.1:1521:xe");  
  8.         //标准协议测试  
  9.         boolean standardFlag1 = driver.acceptsURL("jdbc:oracle:thin:@//<host>:<port>/ServiceName");  
  10.         boolean standardFlag2 = driver.acceptsURL("jdbc:oracle:thin:@<host>:<port>:<SID>");  
  11.         System.out.println("协议测试:"+flag+"\\t"+standardFlag1+"\\t"+standardFlag2);  
  12.           
  13.         //3.创建真实的数据库连接:终结篇:MyBatis原理深入解析

    JDBC 驱动加载原理解析

    Mybatis原理分析一 从JDBC到Mybaits

    Mybatis实现原理深入解析 (转载)

    jvm原理(24)通过JDBC驱动加载深刻理解线程上下文类加载器机制

    关于Class对象类加载机制虚拟机运行时的内存布局的全面解析和推测