一、Class.forName()

在Java中我们一般用下面这样的语句来连接数据库(以MySQL为例)

Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

其实我们还可以这样:

com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();
con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

或者:

new com.mysql.jdbc.Driver();
con=DriverManager.getConnection("jdbc:mysql://"+dbServerIP+":"+dbPort+"/"+dbName,userName,passWord);

  在java中使用JDBC连接数据库时,我们需要知道下面这些信息,却很少去一探究竟

    (1)数据库类型:MySQL、SQL Server、Oracle等

    (2)驱动程序jar包:相应的数据库驱动jar包,如mysql-connector-java-5.1.5-bin.jar等

    (3)驱动类:com.mysql.jdbc.Driver

    (4)JDBC URL:jdbc:mysql:// dbServerIP:dbPort/dbName

  从前面的程序段中我们知道,只要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中并且完成了类的初始化工作,程序就可以正常运行了。

  注意:如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。

com.mysql.jdbc.Driver driver = null;

或者:

ClassLoader cl = new ClassLoader();
cl.loadClass("com.mysql.jdbc.Driver");

二、Bridge模式

  JDBC是使用Bridge模式进行设计的,DriverManager是其中的Abstraction(业务抽象角色,公司),java.sql.Driver是Implementor(业务实现角色,产品),com.mysql.jdbc.Driver是Implementor的一个具体实现(某个具体的产品,衣服);需要注意的是,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。

  Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去,这是怎么回事呢?

  JDK文档对Driver的描述如下图所示:

从上图的描述可知com.mysql.jdbc.Driver在装载后自动帮我们完成了创建实例、注册等步骤,根据上述分析可知,按如下方式修改JDBC驱动的装载,程序同样可以执行:

ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = cl.loadClass("com.mysql.jdbc.Driver");
clazz.newInstance();
Connection conn = DriverManager.getConnection("jdbcurl");

即有:

Class.forName("com.mysql.jdbc.Driver") == cl.loadClass("com.mysql.jdbc.Driver").newInstance();

ClassLoader.loadClass(xxx.xx.xx)仅加载某个类,但并没有实例化;Class.forName(String className)这个方法会做以下几件事情:装载、连接、初始化

Class.forName(xxx.xx.xx) 返回一个类,与 new 的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。


三、Driver的源代码

com.mysql.jdbc.Driver的源代码如下:

package com.mysql.jdbc;

import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
// ~ Static fields/initializers
// --------------------------------------------- //
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
} // ~ Constructors
// ----------------------------------------------------------- /**
* Construct a new driver and register it with DriverManager
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}

扩展A

现有下面这样一道题目,考察对驱动程序的认识

题目解析:


扩展B

jvm在加载类的时候是不会执行静态代码的,只有在初始化的时候才会去执行


参考资料

(1)http://www.ticmy.com/?p=249

(2)http://www.cnblogs.com/sunzn/p/3187868.html

JDBC剖析篇(1):java中的Class.forName()的更多相关文章

  1. JDBC剖析篇(2):JDBC之PreparedStatement

    一次有人问我为什么要使用JDBC中的PreparedStatement,我说可以“防止SQL注入”,其他的却不能说出个一二三,现在来看看其中的秘密 参考文章: http://www.jb51.net/ ...

  2. Java从入门到精通——数据库篇之JAVA中的对Oracle数据库操作

    在Java中对Oracle数据库的操作分为两种:一.查询.二.非查询. 下面是我对其进行总结: 一.查询数据 /** * 根据用户代码查询 * @param userId * @return 如果存在 ...

  3. Java中的Class.forName

    在做JAVA EE开发的过程中,更多的是使用框架来提高开发效率.越来越发现,之前很基础的一些东西,都忘记的差不多了.从今天开始慢慢的复习一下基础.今天在看JDBC的时候,就有一个有趣的地方,之前学的时 ...

  4. java中的Class.forName的作用

    Class.forName有什么作用 Class.forName(xxx.xx.xx) 返回的是一个类 首先你要明白在java里面任何class都要装载在虚拟机上才能运行.这句话就是装载类用的(和ne ...

  5. 《Android进阶》之第一篇 在Java中调用C库函数

    在Java代码中通过JNI调用C函数的步骤如下: 第一步:编写Java代码 class HelloJNI{ native void printHello(); native void printStr ...

  6. 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇

    本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  7. java中String类学习

    java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...

  8. java中为什么重写equals时必须重写hashCode方法?

    在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...

  9. Java中的IO流(五)

    上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...

随机推荐

  1. ACM-ICPC (10/12)

    01分数规划 背景:根据楼教主回忆,曾经在一场比赛中秒掉了一道最优比例生成树问题,导致很多人跟风失败,最终悲剧. 什么是01分数规划呢? 这样的等式求最大,最小即为01分数规划.  如果你不知道该如何 ...

  2. sqlite迁移mysql(导入导出数据)

    第一步,将数据导出 进入sqlite3->.open [打开文件路径]->.cd [要保存的路径]->.output [导出文件名字.sql]->.dump 等待导出成功后,就 ...

  3. requireJs sass侧边栏

    koala 下载 将sass编译为css文件 1 嵌套 2 $变量 3 @mixin 函数名(参数) 4 @include 函数    调用 5 @import "xxx"   引 ...

  4. LeetCode4.寻找两个有序数组的中位数 JavaScript

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2  ...

  5. BionicApi 学习笔记

    1.内存管理 malloc, realloc, free new, delete2.文件输入操作 fopen, fwrite, fputs, fputc, fprintf, fflush fread, ...

  6. Oracle树形结构数据---常见处理情景

    Oracle树形结构数据---常见处理情景 1.查看表数据结构 SELECT *      FROM QIANCODE.TREE_HIS_TABLE T  ORDER BY T.NODE_LEVEL; ...

  7. the “inner class” idiom

    有些时候我们需要upcast为多种类型,这种情况下除了可以使用multiply inherits还可以inner class. 以下为例子: //: C10:InnerClassIdiom.cpp / ...

  8. Jmeter的安装教程【图文】

    Jmeter是一款开源的测试工具,其安装分为两大部分:JDK和Jmeter 第一部分:安装JDK 第一步: 官网下载JDK,可以按照引用地址jdk下载教程进行下载,下载完毕后,进行安装即可 第二步: ...

  9. docker 启动 nginx 访问不了的问题

    使用版本:nginx version: nginx/1.13.8 正使用docker启动nginx容器的时候,一切都很正常,容器也起来了 docker run -dit -p 80:80 --name ...

  10. JavaScript鼠标事件

    mousedown 鼠标被按下. mouseup 鼠标按钮被释放(抬起). click 鼠标左键(或中建)被单击. 事件触发顺序:mousedown>mouseup>click>db ...