源码分析:
这是Mysql 8.x版的java驱动部分源码
package com.mysql.cj.jdbc;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/**
* 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()
}
}
通过在Driver里的static静态代码块调用java.sql.DriverManager.registerDriver()方法来注册数据库驱动.
public class DriverManager {
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
.... //省略代码
}
调用registerDriver后,驱动将会被添加到DriverManager的一个线程安全的List中(registeredDrivers)
而当我们通过DriverManager.getConnection()来获得数据库连接时,会从这个list中去除第一个符合要求的driver,在调用driver.connect()获得一个Connection
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
if (url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
ensureDriversInitialized();
// Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
//这里遍历已注册驱动
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());
//这里获得Connection
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());
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
总结:
按Effective Java里的说法,这是服务提供者框架模式,服务接口是java.sql.Driver,提供者注册API是java.sql.DriverManager.registerDriver(),服务访问API是DriverManager.getConnection().这样做的好处是解耦,服务接收者与服务提供者完全解耦,服务接受者不许要指导服务提供者的具体内容即可调用其服务.
欢迎访问我的 个人网站(主要), Github, CSDN(主要), 博客园, 简书, 掘金, 知乎, 微信公众号:HelloVant(主要)