Class.forName和registerDriver的区别

我们都知道JDBC的代码怎么写,比如以MySQL JDBC为例

 //注册JDBC驱动
Class.forName("com.mysql.jdbc.Driver");

//然后就可以拿到JDB的连接
DriverManager.getConnection("jdbc:mysql://localhost/quickstart", "root", "!123456"); 

通过阅读MySQL JDBC的 源代码,本文将讲述这两段代码背后的内容

1. Class.forName做了什么?
2. java.sql.DriverManager.registerDriver(new Driver())做了什么?

下面详细介绍

1. Class.forName做了什么?

使用Class.forName()会将调用的类初始化,即调用class中的static块,并返回该类的Class对象。比如: com.mysql.jdbc.Driver中代码,当调用Class.forName(“com.mysql.jdbc.Driver”)时,Driver类中static部分就会被调用。

static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
    throw new RuntimeException("Can‘t register driver!");
    }
}

2. java.sql.DriverManager.registerDriver(new Driver())做了什么?
在开始介绍之前先说明2点
(1) com.mysql.jdbc.Driver 的构造函数new Driver()是空的。
(2) 给DriverManager设置一个LogWriter, 可以看到更多log信, DriverManager.setLogWriter(new java.io.PrintWriter(System.out));

其实registerDriver方法做的事情很简单, registerDriver先初始化自己,然后将Driver实例添加到DriverManager中的2个Vector中:readDrivers, writeDrivers

3. DriverManager.getConnection做了什么?
遍历readDrivers, 找到合适的JDBC Driver然后调用其connect方法得到连接,具体怎么得到的连接,我们下一篇文章中将介绍。

下面通过两个例子说明这两个接口
例子1:查看DriverManager.getConnection()log
比如我注册了两个Driver, 一个是Sybase的JDBC Driver,一个是MySQL的JDBC Driver

Class.forName("com.sybase.jdbc2.jdbc.SybDriver");
Class.forName("com.mysql.jdbc.Driver");

DriverManager.getConnection("jdbc:mysql://localhost/quickstart", "root", "!QAZxsw2");
        

运行这段代码,你可以看到如下log (记得在这段代码前设置LogWriter, DriverManager.setLogWriter(new java.io.PrintWriter(System.out));)

static init
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
registerDriver: driver[className=com.sybase.jdbc2.jdbc.SybDriver,[email protected]]
registerDriver: driver[className=com.mysql.jdbc.Driver,[email protected]]

java.sql.DriverManager.registerDriver(new Driver())
DriverManager.getConnection("jdbc:mysql://localhost/quickstart")
    trying driver[className=com.sybase.jdbc2.jdbc.SybDriver,[email protected]]
    trying driver[className=com.mysql.jdbc.Driver,[email protected]]
 //遍历每个注册过得Driver,这里MySQL Driver在第二个,所以第二次才成功

getConnection returning driver[className=com.mysql.jdbc.Driver,[email protected]]

例子2:实现自己的JDBC 驱动

写一个MyDriver.java类,实现java.sql.Driver接口, MyConnection.java类,实现java.sql.Connection(1)在MyDriver.java中,类似com.mysql.jdbc.Driver中的static{}代码,注册自己
(2)并实现自己的acceptUrl,定义你的JDBC URL格式

//TODO,代码在另一台机器上,下次贴上。

运行以后,可以看到如下log信息

static init
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
registerDriver: driver[className=com.sybase.jdbc2.jdbc.SybDriver,[email protected]]
registerDriver: driver[className=com.mysql.jdbc.Driver,[email protected]]
registerDriver: driver[className=com.mysql.jdbc.test.MyDriver,[email protected]]//注册我自己写的驱动

java.sql.DriverManager.registerDriver(new MyDriver())
DriverManager.getConnection("jdbc:my_test_driver://localhost/quickstart") //我自己定义个格式
    trying driver[className=com.sybase.jdbc2.jdbc.SybDriver,[email protected]]
    trying driver[className=com.mysql.jdbc.Driver,[email protected]]
    trying driver[className=com.mysql.jdbc.test.MyDriver,[email protected]]
//因为注册驱动的时候,我放在第三个,所以第三次的时候成功了。
return MyDriver okgetConnection returning driver[className=com.mysql.jdbc.test.MyDriver,[email protected]]

下面是一种常见的方式---

时间: 2024-10-14 14:00:37

Class.forName和registerDriver的区别的相关文章

在java反射中 Class.forName和classLoader的区别

解释 在java中,Class.forName()和ClassLoader()都可以对类进行加载,ClassLoader就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是"通过一个类的全限定名来获取描述此类的二进制字节流",获取到二进制流后放到JVM中.Class.forName()方法实际上也是调用的CLassLoader来实现的. Class.forName(String className)这个方法的源码是: 最后调用的方法是forName0这个方法,在这个forN

在 Java 的反射中,Class.forName 和 ClassLoader 的区别

1. 解释 在java中Class.forName()和ClassLoader都可以对类进行加载.ClassLoader就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是“通过一个类的全限定名来获取描述此类的二进制字节流”,获取到二进制流后放到JVM中.Class.forName()方法实际上也是调用的CLassLoader来实现的. Class.forName(String className)  的源码如下: 1 @CallerSensitive 2 public static

Java反射中Class.forName与classLoader的区别

Java中的class.forName和classLoader都可以用来对类的加载. class.forName除了把类加载到JVM中,还会对类进行解释,执行类的static代码块: classLoader只是把类加载到JVM中,只有在调用newInstance的时候才会去执行static代码块: class.forName的源码如下,对static块的执行是可用控制的,第二个参数为True则执行 public static Class<?> forName(String className)

类加载的三种方式比较

虚拟机加载类的途径 1.由 new 关键字创建一个类的实例 在由运行时刻用 new 方法载入 如:Dog dog = new Dog(): 2.调用 Class.forName() 方法 通过反射加载类型,并创建对象实例 如:Class clazz = Class.forName(“Dog”): Object dog =clazz.newInstance(): 3.调用某个 ClassLoader 实例的 loadClass() 方法 通过该 ClassLoader 实例的 loadClass(

[JVM] JVM类加载机制总结

一  什么是类的加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 类的加载指的是将类从“.java”代码文件编译成的“.class”字节码文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区(HotSpot虚拟机在方法区中)创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象

资料-Java基础:类加载方式及差异

虚拟机加载类的途径1.由 new 关键字创建一个类的实例在由运行时刻用 new 方法载入如:Dog dog = new Dog():2.调用 Class.forName() 方法通过反射加载类型,并创建对象实例如:Class clazz = Class.forName(“Dog”):Object dog =clazz.newInstance():3.调用某个 ClassLoader 实例的 loadClass() 方法通过该 ClassLoader 实例的 loadClass() 方法载入.应用

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Java开发岗位面试题

看到一些java面试题,准备慢慢自己做出来试试. 一.Java基础 1. String类为什么是final的. 只有当字符串是不可变的,字符串池才有可能实现.字符串池的实现可以在运行时节约很多heap空间,因为不同的字符串变量都指向池中的同一个字符串.但如果字符串是可变的,那么String interning将不能实现(注:String interning是指对不同的字符串仅仅只保存一个,即不会保存多个相同的字符串.),因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变

java内存理解与优化

篇幅较长预警 为了方便解释java内存机制,先从类的加载开始谈起 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个类被"首次主动使用"时再加载它(Java首先是通