在使用Class.forName(com.mysql.jdbc.Driver);
的时候会加载这个Driver类,这个Driver类中有静态代码块调用DriverManager.registerDriver(new Driver());
语句注册驱动,静态代码块在加载类的时候就会执行,因此利用反射加载这个类就可以完成注册。
而DriverManager
类里面有属性private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>()
,这个集合保存了的是DriverInfo
类型,这个类型包括注册的驱动和一个对应的data信息,这个data信息直接注册其实为null:
//源码
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
//这里用的是java里面的Driver接口接收jar包里面的Driver对象,因为它实现了这个接口
registerDriver(driver, null);//直接是null!!!
}
public static synchronized void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
然后在使用DriverManager.getConnection()
得到连接的时候底层是遍历registeredDrivers
集合得到一个DriverInfo
对象aDriver
,然后用aDriver对象调用这个对象里面接收驱动的属性driver
,这个driver
就是我们new出来传入的,再用这个driver调用connect方法:
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
//下面这句话就是得到这个我们传入的驱动再调connect!!!!!!!!!!!!!!!!
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
- 由上可知,我们虽然不推荐用直接
new Driver()
得到Driver对象再调用connect方法得到连接,但是用DriverManager
得到连接的时候底层仍然是在Class.forName()
new一个Driver对象注册进去,然后找出这个对象用它调用connect方法来得到连接。因此使用Class.forName()
注册驱动必不可少,不然DriverManager里面的驱动集合里找不到它,无法进行连接。