本文系转载,地址: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)驱动源码分析(二)相关推荐

  1. java mysql 源码分析_JAVA JDBC(MySQL)驱动源码分析

    JAVA连接数据库是其众多功能中的一部分,主要有两种方式连接DataBase: 一种是采用JDBC-ODBC桥,另一种则是称之为纯驱动连接DataBase,第一种方式在大型项目中基本上不再使用,本系列 ...

  2. java连接mysql数据库增删改查_java连接mysql数据库增删改查操作记录

    1. 连接数据库.得到数据库连接变量 注意连接数据库的时候 (1)打开DB Browser 新建一个Database Driver,注意加入Driver JARs的时候加入的包,我的是mysql-co ...

  3. mysql jdbc怎么用问号传参_java – jdbc PreparedStatement中的问号问题

    我来回浏览互联网,发现我的问题无法解决. 我试图使用参数绑定与jdbc查询mysql表,但它在我的语句中不断报告问号的语法错误. 这是我的班级: package todoList_; import j ...

  4. mysql的左右连接 分页_Java 与 Mysql连接,并分页显示

    这是我第一个上规模的Java项目,我们必须在一周内完成的作业,零基础学习Java,网上收集了很多资料,逐渐对面向对象的思想有所了解,但还是半灌水,后期打算结合项目系统地学习一遍Java.老师布置的任务 ...

  5. java servlet项目源码下载_java网上商城项目源码(jsp.servlet+javabean+mysql+jdbc)

    [实例简介] 网上商城所有基本功能实现. 包含所有图片等资源 包含数据库创建脚步 开发环境 jdk1.7 myeclipse10 tomcat6.0 mysql 5 [实例截图] [核心代码] 325 ...

  6. java futuretask 源码解析_Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  7. java泡泡堂分析_java泡泡堂 - WEB源码|JSP源码/Java|源代码 - 源码中国

    文件名大小更新时间 CrazyArcade\.classpath2952019-11-23 CrazyArcade\.gitignore12052019-11-23 CrazyArcade\.proj ...

  8. java.lang 源码剖析_java.lang.Void类源码解析

    在一次源码查看ThreadGroup的时候,看到一段代码,为以下: /* * @throws NullPointerException if the parent argument is {@code ...

  9. mysql的收银软件_java swing mysql实现的超市收银进销存系统项目源码附带视频指导运行教程...

    <p> <span style="color:#555555;font-family:"font-size:16px;background-color:#FFFF ...

最新文章

  1. java URI 与URL问题
  2. linux shell 脚本练习,shell脚本小练习
  3. 【转载】负数的二进制
  4. 可变形卷积神经网络 | Deformable Network
  5. 《高可用架构·中国初创故事(第3期)》一1.4 认同企业文化
  6. java赋值两个对象数组 clone_有关java对象数组的clone问题
  7. VC++使用CImage在内存中Bmp转换Jpeg图片
  8. php 递归中的全局变量,PHP递归函数内的静态变量
  9. ubuntu+网易云安装
  10. feign.RetryableException: connect timed out executing xxxxxx
  11. 体验APP时的必答题—以扇贝单词为例
  12. 【机器学习基础】CH2 - 监督学习(5)决策树
  13. 【Android】Android Window
  14. Creating and Configuring a CDB
  15. solidworks报错合集
  16. 读书笔记 | 自动驾驶中的雷达信号处理(第9章 汽车雷达的应用概述)
  17. 小程序开发.云数据库
  18. python计算圆周率100万位要多久_Super Pi-计算10000位圆周率需要多少时间?
  19. 公链应用争夺战:未来区块链生态真的“根特多,叶子少”?
  20. python3爬虫进阶之自动登录网易云音乐并爬取指定歌曲评论

热门文章

  1. 直击“上云”痛点的 MSP 新生意
  2. 打破云原生时代存储瓶颈,SmartX 发布 K8s 云原生存储 IOMesh
  3. 大厂技术文档:Python基础+爬虫+数据分析+面试经精选
  4. 图文+动画讲解排序算法总结!!
  5. 重装linux之后gcc等下载不了,Redhat linux下安装gcc
  6. 把所有圆圈连接起来的游戏_20个幼儿园体育小游戏教程
  7. 自定义导航页_带你回归“真”的导航页
  8. linux如何设置mac快捷键,在Ubuntu上使用macOS的快捷键
  9. php组成,PHP的控制结构,PHP脚本是由一系列语句组成的。
  10. mysql管理器源码_一个HelloWorld版的MySQL数据库管理器的设计与实现(源码)