java jdbc(mysql)驱动源码分析_JAVA JDBC(MySQL)驱动源码分析(二)

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/528538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java %3c%=a%%3e_跪求帮忙解析,急!!!

xml 这个参数的值&#xff0c;是被 urlencode 两次的东西。 php 不懂&#xff0c; Python 的话是用 urllib.unquote 就可以了。>>> s %3C%3Fxmlversion%3D%221.0%22encoding%3D%22gbk%22%3F%3E%253Ctask%253E%253Cuser%253E%253Coper%253Emod%253C%252Foper%253E%253…

java环境变量一闪而过_Java环境变量配置和Tomcat启动时cmd界面一闪而过问题

Java环境变量配置计算机 -> 属性 -> 高级系统设置 -> 环境变量 -> 系统变量中配置Java环境变量。配置JAVA_HOME&#xff0c;属于必配项&#xff0c;如果不配置&#xff0c;直接指定path路径利用工具可以进行Java项目开发&#xff0c;但是后期使用Tomcat开发会出现问…

ubuntu启动php-fpm_ubuntu安装php-fpm+xdebug

一、安装程序包1、sudo apt-get install php5-dev2、sudo apt-get install php5-xdebug二、修改php.ini配置文件; 修改/etc/php5/fpm/php.ini或在增加文件/etc/init.d/php5/conf.d/xdebug.ini; configuration for php Xdebug module;extentionxdebug.so[xdebug]zend_extension/…

php 图片合成,PHP中多张图片合成一张图片例子

今天分享一段PHP中多张图片合成一张图片的代码实现&#xff0c;我们可以在图片合成&#xff0c;水印&#xff0c;九宫格等需求下使用到类似这样的图片合成效果,下面一起来看看例子吧。今天分享一段PHP中多张图片合成一张图片的代码实现&#xff0c;我们可以在图片合成&#xff…

php的cms是什么意思,phpcms是什么

phpcms是一款具备文章、下载、图片、分类信息、影视、商城、采集、财务等众多功能的强大、易用、可扩展的优秀网站管理软件&#xff1b;该软件采用模块化开发&#xff0c;支持多种分类方式&#xff0c;使其可方便实现个性化网站的设计、开发与维护。phpcms是一款具备文章、下载…

php5.4源码下载,WordPress v5.4.2官方正式版源码下载

源码说明WordPress 5.4.2 正式版发布了&#xff0c;此安全和维护版本具有23个修复和增强功能。此外&#xff0c;它还添加了许多安全修复程序-请参阅下面的列表。这些错误会影响WordPress 5.4.1和更早版本。5.4.2版修复了这些问题&#xff0c;因此您需要升级。如果尚未更新到5.4…

前端vue后端java,Vue调用后端java接口的实例代码_亦心_前端开发者

前段时间 做了个学校的春萌项目&#xff0c;其中用到先上后端接口代码&#xff1a;package controller;import net.sf.json.JSONObject;import util.DBUtil;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.Http…

边缘检测滤波matlab,卷积滤波器与边缘检测

频率&#xff1a;对于声音&#xff0c;频率实际上是指声波振荡的速度高低频率高频图像是强度变化很大的图像。并且亮度级别从一个像素到下一个像素快速变化。低频图像可以是亮度相对均匀或变化非常慢的图像。这是一个例子中最容易看到的。大多数图像都有高频和低频成分。在上图…

php 读取 stl 文件,科学网—[转载]【源码】读取ASCII STL文件的STLReader - 刘春静的博文...

读取包含顶点和面的ASCII STL文件&#xff0c;并将其构造为矩阵“顶点”、“颜色”和“面”。之后&#xff0c;使用各小模块在Matlab上建立模型。Read ASCII STL file which contains vertexes and faces and structure it to matrixes "vertexes", "colors&quo…

1核1g服务器php,虚拟主机1核1g什么意思

虚拟主机由于用户数量庞大&#xff0c;因此每个虚拟主机需要足够高的配置才能支持这么多网站同时架设、运行&#xff0c;如上面所说的1核&#xff0c;完全没法带动。比如那么我们平常怎么知道自己的虚拟主机配置是怎样的呢&#xff1f;可以直接咨询下面我们来看下西部数码虚拟主…

matlab生成西门子plc源文件,西门子PLC如何把DB快做成源文件

打开db块后在菜单option下面有个customize&#xff0c;弹出的点选项sources那里就可以找到生成源文件的按钮。还原---源文件是保存在sources下面&#xff0c;你可以打开你的源文件并编译即可生成源文件可以导出成awl文件&#xff0c;可以在其他的环境下改写(比如记事本、excel等…

dsm php,docker dsm是什么?

docker dsm是什么&#xff1f;docker dsm是&#xff1a;从DSM6.0开始如果装了docker的话可以看到下面的图&#xff1a;上图可以看到创建了一个新的DSM&#xff0c;名字为DDSM1&#xff0c;经试验功能和正式DSM一模一样。同时白裙一样可以QuickConnect。然后用Putty登录上去&…

php 5.6 文档,文件存储 | 进阶系列 | Laravel 5.6 中文文档

文件存储由 学院君 创建于3年前, 最后更新于 1年前版本号 #231608 views3 likes0 collects简介Laravel 基于 Frank de Jonge 开发的 PHP 包 Flysystem 提供了强大的文件系统抽象层。Laravel 集成 Flysystem 以便使用不同驱动简化对文件系统的操作&#xff0c;这些驱动包括本地文…

oracle创建主键开并行,Oracle并行添加主键

2.考虑先并行添加惟一性索引&#xff0c;再添加主键SQL> create unique index pk_t on t(object_id) parallel 2 online; Index createdSQL> alter table t add constraint pk_t primary key (object_id); Table alteredSQL> alter index pk_t noparallel; Index alte…

阐述oracle的体系结构,Oracle数据库逻辑体系结构详解

以前对Oracle数据库的了解大多数是集中在mysql&#xff0c;最近工作里面一直使用的是Oracle&#xff0c;虽然说在互联网行业mysql大行其道&#xff0c;但是一些传统行业或者是金融领域还是更加倾向于使用oracle&#xff0c;sqlserver这种大型数据库。为此还是有必要深入了解以下…

oracle如何规则显示,Oracle语句优化规则汇总

Oracle sql 性能优化调整1. 选用适合的ORACLE优化器ORACLE的优化器共有3种&#xff1a;a. RULE (基于规则)b. COST (基于成本)c. CHOOSE (选择性)设置缺省的优化器&#xff0c;可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明&#xff0c;如RULE&#xff0c;COST&#x…

手机版数据库oracle,用手机管理及维护MySQL,Oracle等数据库

sql server 导出的datetime结果 CAST&lpar;0x00009E0E0095524F AS DateTime&rpar; 如何向mysql&comma;oracle等数据库进行转换1. 处理 sql server 导出的 datetime 类型的字段 在进行sql server向mysql等其他数据进行迁移数据时,会发现使用sql server导出的datetim…

PHP如何读取excel文,PHP-php如何读取excel?

我前几天刚好也用到了PHP读取Excel我用的是phpexcel最新的版本。下面是代码require_once ./PHPExcel/PHPExcel.php;$_ReadExcel new PHPExcel_Reader_Excel2007();//为了可以读取所有版本Excel文件if(!$_ReadExcel->canRead(PATH./.$_data[path])) $_ReadExcel new PHPExc…

小青蛙oracle跟踪,Oracle 存储过程:游标

一、认识游标什么是游标&#xff1f;游标是数据库的一种数据类型&#xff0c;它用来管理从数据源(表&#xff0c;视图等)获取到的数据结果集&#xff0c;可以想象成一个游动的光标(指针)&#xff0c;指向一个结果集&#xff0c;通过游标的移动逐行提取每一行的记录&#xff0c;…

linux使用设备文件的目录,Linux系统下的/dev目录

dev是设备(device)的英文缩写。/dev这个目录对所有的用户都十分重要。下面学习啦小编给大家分享详解Linux系统下的/dev目录&#xff0c;欢迎阅读&#xff1a;详解Linux系统下的/dev目录&#xff1a;在这个目录中包含了所有linux系统中使用的外部设备。但是这里并不是放的外部设…