我们都知道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,com.sybase.jdbc2.jdbc.SybDriver@42e816]
registerDriver: driver[className=com.mysql.jdbc.Driver,com.mysql.jdbc.Driver@de6ced]

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

getConnection returning driver[className=com.mysql.jdbc.Driver,com.mysql.jdbc.Driver@de6ced]

例子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,com.sybase.jdbc2.jdbc.SybDriver@42e816]
registerDriver: driver[className=com.mysql.jdbc.Driver,com.mysql.jdbc.Driver@de6ced]
registerDriver: driver[className=com.mysql.jdbc.test.MyDriver,com.mysql.jdbc.test.MyDriver@1fb8ee3]//注册我自己写的驱动

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

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

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

  1. 反射中Class.forName()和classLoader的区别

    搞清楚两者之间区别前,我们来了解下类加载过程. 一.类加载过程 1.加载 通过一个类的全限定名来获取定义此类的二进制字节流. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构. 在内存中生 ...

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

    前言 最近在面试过程中有被问到,在Java反射中Class.forName()加载类和使用ClassLoader加载类的区别.当时没有想出来后来自己研究了一下就写下来记录一下. 解释 在java中Cl ...

  3. Class.forName和ClassLoader.loadClass区别(转)

    Java中class是如何加载到JVM中的:1.class加载到JVM中有三个步骤    装载:(loading)找到class对应的字节码文件.    连接:(linking)将对应的字节码文件读入 ...

  4. 反射中,Class.forName 和 classloader 的区别

    https://blog.csdn.net/qq_27093465/article/details/52262340 java中class.forName()和classLoader都可用来对类进行加 ...

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

    1. 解释 在java中Class.forName()和ClassLoader都可以对类进行加载.ClassLoader就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是“通过一个类的全 ...

  6. Java反射中Class.forName和classloader的区别

    Java中Class.forName和classloader都可以用来对类进行加载. Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块 ...

  7. Class.forName和ClassLoader的区别

    一 看名字就知道了,一个是类的创建,一个类加载器 二 再看下Class.forName源码,调用了ClassLoader @CallerSensitive public static Class< ...

  8. class.forName 和 classLoader的区别

    Java中的Class.forName()和ClassLoader都可以用来对类进行加载.Class.forName()除了将类的.class文件加载到JVM中 还会对类进行解释,执行类中的stati ...

  9. class.forName() 和 classLoader 的区别

    相同点:        java中class.forName() 和 classLoader 都可用来对类进行加载 不同店:        1.class.forName()除了将类的 .class ...

随机推荐

  1. C++反汇编-继承和多重继承

    学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然 ...

  2. mount nfs 经常出错信息总结(转)

    通常当NFS不能正常使用时候会给出提示,一般给出一下几种: 1)mount: 192.168.1.111:/opt failed, reason given by server: Permission ...

  3. C#值类型装箱后能改变其值吗

    当把一个值类型赋值给引用类型,这个过程可以看作是"装箱". ; 以上,堆栈上的过程大致是:1.在栈上开辟空间给变量a2.在堆上开辟空间,习惯上把该空间看作是"箱子&quo ...

  4. java多线程知识点汇总(一)多线程基础

    1.什么叫多线程程序? 答:一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序. java编写的程序都是多线程的,因为最少有俩线程,main主线程和gc线程. ...

  5. 相比xib 使用代码编排view 的一个明显的好处就是可以更好地重复使用已有代码,减少代码冗余。

    相比xib 使用代码编排view 的一个明显的好处就是可以更好地重复使用已有代码,减少代码冗余.

  6. javascript级联菜单,数据从数据库中获取

    1.html代码: <%@ page contentType="text/html; charset=gb2312" %> <%@ page import=&qu ...

  7. ping + 时间 日志

    :top set PINGIP="192.168.1.236" echo %date% %time%>>%PINGIP%.txt ping -n 1 %PINGIP% ...

  8. 关于查询排序DTO的封装

    DTO: public class SortDto { //排序方式 private String orderType; //排序字段 private String orderField; publi ...

  9. org-mode入门教程

    org-mode 入门教程By Z.H. Fu 切问录 www.fuzihao.org org-mode 入门教程 org-mode是Emacs提供的一个强大的编辑模式,可以用于做会议笔记以及制作各种 ...

  10. iOS:NSBundle的具体介绍

    NSBundle介绍:它是一个单例类,用来加载资源 bundle是一个目录,其中包含了程序会使用到的资源. 这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-i ...