1. 代码
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/liusheng", "xxx", "xx");
2. 第一行
我们都知道是向DriverManager注册驱动
因为 Class.forName 默认初始化类 ,所以以下代码会执行
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
具体的是:
// 就是想CopyOnWriteList添加一个驱动(如果不存在)
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
3 第二行
就是获取连接 Connection 具体是
获取调用者的Class就是我们Main类
(getConnection(url, info, Reflection.getCallerClass()))
接下来:
// 获取我们调用者ClassLoader (一般是Launcher$AppClassLoader)
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// 如果ClassLoader是Boot加载器 ,那么就设置为上下文加载器
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
SQLException reason = null;
// 遍历说有注册的驱动
for(DriverInfo aDriver : registeredDrivers) {
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
// 连接失败,或者 url 与驱动不匹配,那么久会抛异常,或者返回null ,由于下面会捕获异常,所以会继续尝试
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
}
}
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
throw new SQLException("No suitable driver found for "+ url, "08001");
判断方法 isDriverAllowed
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
boolean result = false;
if(driver != null) {
Class<?> aClass = null;
try {
// 回去调用者(对我们来说Main类)ClassLoader来加载
aClass = Class.forName(driver.getClass().getName(), true, classLoader);
} catch (Exception ex) {
result = false;
}
// 如果 两个Class是相同的,则表示驱动加载正确 ,这是为了防止,注册的实例和SPI(Service Provider Interface)使用的Class不同,从而出现错误,所以我们接下来让两个驱动不同,就会导致Class.forName 之后,也获取不到驱动
result = ( aClass == driver.getClass() ) ? true : false;
}
return result;
}
4.例子
1. 自定义ClassLoader
这个ClassLoader 从我们桌面获取Mysql驱动jar包,并加载
// 直接继承 URLClassLoader即可
public class MysqlClassLoade extends URLClassLoader {
public MysqlClassLoade() throws MalformedURLException {
super(new URL[]{Paths.get("C:\\Users\\Administrator\\Desktop\\mysql.jar").toUri().toURL()});
}
}
2. Main类
public static void main(String[] args) throws ClassNotFoundException, MalformedURLException, SQLException {
try {
Class.forName("com.mysql.jdbc.Driver", true, new MysqlClassLoade());
}catch (Exception e){
System.out.println("加载 驱动失败");
}
try {
Connection connection = DriverManager.getConnection("jdbc:mysql://134.175.9.88:3306/liusheng", "root", "root");
}catch (Exception e){
System.out.println("获取Connection 失败");
}
}
3 输出
说明驱动加载到了 ,但是连接没有获取到(注意:我们的Class Path 下不能有Mysql驱动,因为ClassLoader是双亲委托机制的 ,会先让父加载器加载一下)