JDBC剖析篇(1):java中的Class.forName()
一、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()的更多相关文章
- JDBC剖析篇(2):JDBC之PreparedStatement
一次有人问我为什么要使用JDBC中的PreparedStatement,我说可以“防止SQL注入”,其他的却不能说出个一二三,现在来看看其中的秘密 参考文章: http://www.jb51.net/ ...
- Java从入门到精通——数据库篇之JAVA中的对Oracle数据库操作
在Java中对Oracle数据库的操作分为两种:一.查询.二.非查询. 下面是我对其进行总结: 一.查询数据 /** * 根据用户代码查询 * @param userId * @return 如果存在 ...
- Java中的Class.forName
在做JAVA EE开发的过程中,更多的是使用框架来提高开发效率.越来越发现,之前很基础的一些东西,都忘记的差不多了.从今天开始慢慢的复习一下基础.今天在看JDBC的时候,就有一个有趣的地方,之前学的时 ...
- java中的Class.forName的作用
Class.forName有什么作用 Class.forName(xxx.xx.xx) 返回的是一个类 首先你要明白在java里面任何class都要装载在虚拟机上才能运行.这句话就是装载类用的(和ne ...
- 《Android进阶》之第一篇 在Java中调用C库函数
在Java代码中通过JNI调用C函数的步骤如下: 第一步:编写Java代码 class HelloJNI{ native void printHello(); native void printStr ...
- 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- java中String类学习
java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...
- java中为什么重写equals时必须重写hashCode方法?
在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...
- Java中的IO流(五)
上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...
随机推荐
- HDU 2048 错排
错排递推公式: d(n) = (n-1)*(d[n-1]+d[n-2]): 证明:将第n个元素放到第k处,第k处的元素如果放到第n处,就是d(n-2),否则,先假设放到第n处,然后错排,就是d(n-1 ...
- 【转】Android 之ActivityThead、ActivityManagerService 与activity的管理和创建
在android中,Activity是四大组件中比较重要的一个(当然其他的也比较重要),那么android中是怎样管理这些activity的?应用的进程和主线程是怎么创建的,应用的消息循环又是在什么时 ...
- NYOJ298 点的变换 【矩阵乘法经典】
任意门:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=298 点的变换 时间限制:2000 ms | 内存限制:65535 KB 难度:5 ...
- Strtus2框架使用HttpServletResponse响应数据
-----------------------------------------------------------------------------------------jsp-------- ...
- 【洛谷P1107】 [BJWC2008]雷涛的小猫
雷涛的小猫 题目链接 n^2DP比较好想, f[i][j]表示第i棵树高度为j的最大收益 直接从上到下转移即可,每次记录下max f[1~n][j] 用于下面的转移 f[i][j]=max(f[i][ ...
- 【luogu P3063 [USACO12DEC]牛奶的路由Milk Routing】 题解
题目链接:https://www.luogu.org/problemnew/show/P3063#sub 我很好奇这道题为什么没被收入SPFA好题 #include <cstdio> #i ...
- PAT1087. All Roads Lead to Rome
PAT1087. All Roads Lead to Rome 题目大意 给定一个图的边权和点权, 求边权最小的路径; 若边权相同, 求点权最大; 若点权相同, 则求平均点权最大. 思路 先通过 Di ...
- C++中的头文件(.h)和源文件(.cpp)都应该写什么?
头文件(.h):写定义和声明写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但是一般来说不写具体的实现.注意: 1.在写头文件的时候需要注意,在开头和结尾处必须按照如下样式 ...
- iOS | CAShapeLayer转场动画
什么也不说了,作为一名乐于分享技术的小开发,直接先上个样式最为直观贴切,有需要的朋友可以直接拿过去用. 需要demo请点击这里 :github 在这个demo中,核心为选用画布CAShapeLayer ...
- 快速排序_C语言_数组
快速排序_C语言_数组 #include <stdio.h> void quickSort(int *, int, int); int searchPos(int *, int, int) ...