Class.forName(“com.mysql.jdbc.Driver”)是 强制JVM将com.mysql.jdbc.Driver这个类加载入内存,并将其注册到DriverManager类,然后根据DriverManager.getConnection(url,user,pwd)中的url找到相应的驱动类,最后调用该该驱动类的connect(url, info)来获得connection对象。

JDBC的驱动管理机制的 具体底层代码分析如下:

1.     分析JDBC的驱动程序管理部分的实现代码:
    
        在 JDBC的层次上,sun主要定义了1个接口Driver和两个类:DirverManager和DriverInfo。每个JDBC驱动程序必须实现 Driver接口(在MySql的Connector/J驱动中,这个叫做com.mysql.jdbc.Driver)。而DriverManager 则负责管理所有的Driver对象,包含注册Driver;选择合适的Driver来建立到某个数据库的连接;以及进行一些Driver的信息管理等。 DriverInfo非常简单,用于保存Driver的信息,只有3个成员变量,Driver,DriverClass和 DriverClassName,意义非常明显。

先看一下在DriverManager.java中的关键代码:
        private static java.util.Vector drivers = new java.util.Vector();
        所有的Driver对象保存在一个Vector数组中。

注册Driver的函数叫registerDriver,将需要注册的Driver对象传入即可:

public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
if (!initialized) { //如果没有初始化,则先初始化
initialize();
}
DriverInfo di = new DriverInfo(); // 实际保存的不是Driver,而是一个DriverInfo对象,但是DriverInfo的其它成员完全可以由Driver推导出来,所以个人觉得 DriverInfo对象可有可无,直接使用Driver应该就可以了。
di.driver = driver;
di.driverClass = driver.getClass();
di.driverClassName = di.driverClass.getName();
drivers.addElement(di); //将DriverInfo对象添加到数组中
println("registerDriver: " + di);
}

在一个类加载入内存的时候,类中的静态初始化过程会执行,这样就完成了驱动程序的注册过程。然后重点看一下建立数据库连接的代码,在getConnection函数中,省略了一些非关键代码:

private static synchronized Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { SQLException reason = null;
//轮询所有的DriverInfo对象。
for (int i = 0; i < drivers.size(); i++) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
try {
//使用DriverInfo中的Driver对象去做实际的连接数据库的工作
Connection result = di.driver.connect(url, info);
if (result != null) {
// Success!
println("getConnection returning " +&bsp;di);
return (result); //一旦成功连接,直接返回Connection对象,然后推出
}
} catch (SQLException ex) {
...
}
}
//这就是经常看到的出错信息--找不到合适的驱动程序。
println("getConnection: no suitable driver");
throw new SQLException("No suitable driver", "08001");
}

由 上面的getConnection函数可以看到,真正实现数据库连接的是Driver对象的connect函数。而且可以看到,由于 DriverManager.getConnection使用的是一种轮询的方式,注册的驱动程序越多,连接速度会越慢。JDBC连接数据库的速度很慢, 是不是和这种实现方式有关联呢?怀着这个问题,本人下载了MySql的Connector/J驱动包,开始分析其connect函数的实现。

2.    分析MySql的注册和建立连接部分的代码:
        打开MySql的源码包,首先分析其Driver类的实现。发现Driver类的实现非常简单,

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}

可 以看到,有一段static代码,调用了DriverManager的registerDriver方法。这其实就解释了 Class.forName(“com.mysql.jdbc.Driver”)能够完成MySql驱动注册的问题。因为forName会导致这段 static代码被调用,从而间接调用了registerDriver,完成注册过程。
        
        com.mysql.jdbc.Driver 从com.mysql.jdbc.NonRegisteringDriver继承而来,实际上是NonReisteringDriver完成了 java.sql.Driver接口的实现工作。转移目标,分析NonRegisteringDriver的connect函数。

NonRegisteringDriver.connect的实现也比较简单,正合我意:

public java.sql.Connection connect(String url, Properties info)
        throws SQLException {

//1.    分析传入的连接字符串.

 if ((props = parseURL(url, info)) == null) {
return null;
}
try {
//2. 建立一个Connection对象完成实际的数据库连接工作
Connection newConn = new com.mysql.jdbc.Connection(host(props),
port(props), props, database(props), url, this);
return newConn;   }

非 常简单,先parseURL,然后使用Connection去建立连接。parseURL只是简单的字符串分析,主要是分析传入的连接字符串是否满足 “jdbc:mysql://host:port/database“的格式,如果不满足,直接返回null,然后由DriverManager去试验下 一个Driver。如果满足,则建立一个Connection对象建立实际的数据库连接,这不是本人关注的问题,源码分析就此打住。

由此可见1中的问题答案是:DriverManager的轮询查询注册的Driver对象的工作方式所带来的性能代价并不是很大,主工作量只是parseURL函数。

JDBC底层原理的更多相关文章

  1. Servlet底层原理、Servlet实现方式、Servlet生命周期

    Servlet简介 Servlet定义 Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序. Servlet的特点 (1)Servlet对像,由Servlet容器 ...

  2. 原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    开心一刻 女孩睡醒玩手机,收到男孩发来一条信息:我要去跟我喜欢的人表白了! 女孩的心猛的一痛,回了条信息:去吧,祝你好运! 男孩回了句:但是我没有勇气说不来,怕被打! 女孩:没事的,我相信你!此时女孩 ...

  3. SpringBoot集成MyBatis底层原理及简易实现

    MyBatis是可以说是目前最主流的Spring持久层框架了,本文主要探讨SpringBoot集成MyBatis的底层原理.完整代码可移步Github. 如何使用MyBatis 一般情况下,我们在Sp ...

  4. 抛开 Spring ,你知道 MyBatis 加载 Mapper 的底层原理吗?

    原文链接:抛开 Spring ,你知道 MyBatis 加载 Mapper 的底层原理吗? 大家都知道,利用 Spring 整合 MyBatis,我们可以直接利用 @MapperScan 注解或者 @ ...

  5. springAop:Aop(Xml)配置,Aop注解配置,spring_Aop综合案例,Aop底层原理分析

    知识点梳理 课堂讲义 0)回顾Spring体系结构 Spring的两个核心:IoC和AOP 1)AOP简介 1.1)OOP开发思路 OOP规定程序开发以类为模型,一切围绕对象进行,OOP中完成某个任务 ...

  6. Activiti工作流学习笔记(三)——自动生成28张数据库表的底层原理分析

    原创/朱季谦 我接触工作流引擎Activiti已有两年之久,但一直都只限于熟悉其各类API的使用,对底层的实现,则存在较大的盲区. Activiti这个开源框架在设计上,其实存在不少值得学习和思考的地 ...

  7. Spring Boot-自动配置之底层原理

    一.SpringBoot启动的时候加载主配置类,开启了自动配置的功能 @SpringBootApplication public class SpringBoot02Application { pub ...

  8. Neo4j图数据库简介和底层原理

    现实中很多数据都是用图来表达的,比如社交网络中人与人的关系.地图数据.或是基因信息等等.RDBMS并不适合表达这类数据,而且由于海量数据的存在,让其显得捉襟见肘.NoSQL数据库的兴起,很好地解决了海 ...

  9. 【T-SQL进阶】02.理解SQL查询的底层原理

    本系列[T-SQL]主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式 ...

随机推荐

  1. 在Intellij IDEA 中clean报错:-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.

    解决办法:添加VM属性   -Dmaven.multiModuleProjectDirectory=$M2_HOME

  2. GitHub For Beginners: Don’t Get Scared, Get Started

    It's 2013, and there's no way around it: you need to learn how to use GitHub.2 Why? Because it's a s ...

  3. CGI编程

    1简介 .CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口,服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间 ...

  4. [JavaScript]自执行函数

    最近在接触mui的时候,遇到了一段代码: (function($, doc) { $.init({ statusBarBackground: '#f7f7f7' }); $.plusReady(fun ...

  5. SQL Server中计算表达式的和

    项目使用的是SQL Server数据库,需要做一个审核规则,字段A中表达式的值和字段B中的值,做比较: 需求本身很简单,但是表达式中存在很多非法字符(非法全角,运算符,汉字--) eg:1.1.1*2 ...

  6. Java基础教程1:环境配置及第一个HelloWorld.java

    本文主要介绍JDK环境配置.Sublime Text3配置及第一个HelloWorld.Java程序.运行环境为Win10系统,使用JDK1.8版本. 1. JDK下载及环境配置 1.1 JDK下载 ...

  7. 18_Python列表常用方法总结

    ''' 1.列表切片索引\截取 2.列表的增删改查 3.列表最大值\列表最小值\排序 4.列表的遍历 5.列表的嵌套 6.列表和字符串的互转 7.判断元素是否在列表中 ''' #列表使用中括号表示 元 ...

  8. thinkpadE470 win10安装虚拟机时出现‘intel VT-x’处于禁用状态 无法执行64位操作系统

    上图为安装虚拟机时弹出的问题. 解决办法: 本人电脑型号为thinkpadE470.遇到此问题查阅了很多,都是针对一般电脑的.折腾了好一会儿.故特写一篇针对此型号的. 1.重启计算机,一开始出现联想标 ...

  9. 《Thinking in Java》学习笔记(六)

    1.Class相关知识 Class类可以理解为类的图纸,通过Class类可以分析类的结构.构建出类的实例. Class.forName("test.TestClass").newI ...

  10. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...