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 中也有详细描述。
这就是初始化的全过程,写了这么多,实际上只做一件事情,就是完成所有驱动的加载。装载之后就是连接了,在连载三当中我会详细描述。
上一篇中分析了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 中也有详细描述。
这就是初始化的全过程,写了这么多,实际上只做一件事情,就是完成所有驱动的加载。装载之后就是连接了,在连载三当中我会详细描述。
相关文章推荐
- JAVA JDBC(MySQL)驱动源码分析
- JAVA JDBC(MySQL)驱动源码分析(一)
- JAVA JDBC(MySQL)驱动源码分析(二)
- JAVA JDBC(MySQL)驱动源码分析(四)
- JAVA JDBC(MySQL)驱动源码分析(三)
- mysql jdbc驱动源码分析(Statement的executeQuery 和executeUpdate方法)
- Mysql JDBC驱动源码分析(加载驱动)一
- mysql jdbc驱动源码分析(获取链接 connection)
- mysql jdbc驱动源码分析(驱动加载)
- mysql jdbc驱动源码分析(获取Statement对象)
- 有关jdbc驱动的问题,java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- JAVA-数据库之MySQL与JDBC驱动下载与安装
- 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)
- 【java源码】jdbc实现增查删改<Mysql>
- 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)
- 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)
- ORM framework源码分析:引言之Java JDBC
- Java JDBC 驱动 MySQL
- MySQL的JDBC驱动源码解析 预编译开启
- mysql驱动配置:解决java.lang.ClassNotFoundException: com.mysql.jdbc.Driver