在初始化 init() 方法中,可以看到2处关于 java.sql.Driver 驱动的方法:
// bug fixed for dead lock, for issue #2980
DruidDriver.getInstance();
resolveDriver();
先来看第1处,看注释是为了解决一个bug而增加的,主要解决了多线程死锁的问题,issue 链接:https://github.com/alibaba/druid/issues/2980
DruidDriver 类的 static 静态块:
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
registerDriver(instance);
return null;
}
});
}
其中 registerDriver(instance) 中的 instance 就是这个类实例对象:
private final static DruidDriver instance = new DruidDriver();
registerDriver(instance) 这个类中比较重要的一行代码如下,就是使用 DriverManager 注册驱动类:
DriverManager.registerDriver(driver);
这里会把 DruidDriver 注册 DriverManager 中。
我们再来看第2处:resolveDriver()
protected void resolveDriver() throws SQLException {
if (this.driver == null) {
// 先判断驱动为空时,进入
if (this.driverClass == null || this.driverClass.isEmpty()) {
// 从 jdbcUrl 中解析字符串类型的 driverClass
this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);
}
if (MockDriver.class.getName().equals(driverClass)) {
driver = MockDriver.instance;
} else if ("com.alibaba.druid.support.clickhouse.BalancedClickhouseDriver".equals(driverClass)) {
Properties info = new Properties();
info.put("user", username);
info.put("password", password);
info.putAll(connectProperties);
driver = new BalancedClickhouseDriver(jdbcUrl, info);
} else {
if (jdbcUrl == null && (driverClass == null || driverClass.length() == 0)) {
throw new SQLException("url not set");
}
// 加载驱动类
driver = JdbcUtils.createDriver(driverClassLoader, driverClass);
}
} else {
// 如果 driver 不为空,获取其类名给 driverClass 赋值
if (this.driverClass == null) {
this.driverClass = driver.getClass().getName();
}
}
}
加载驱动类 JdbcUtils.createDriver(driverClassLoader, driverClass) 方法:
如果传入的类加载器不为空,使用其加载驱动类;
如果为空,使用线程上下文类加载器进行加载;
如果还没有加载到驱动类,使用 Class.forName() 加载;
public static Driver createDriver(ClassLoader classLoader, String driverClassName) throws SQLException {
Class<?> clazz = null;
if (classLoader != null) {
try {
clazz = classLoader.loadClass(driverClassName);
} catch (ClassNotFoundException e) {
// skip
}
}
if (clazz == null) {
try {
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (contextLoader != null) {
clazz = contextLoader.loadClass(driverClassName);
}
} catch (ClassNotFoundException e) {
// skip
}
}
if (clazz == null) {
try {
clazz = Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage(), e);
}
}
try {
return (Driver) clazz.newInstance();
} catch (IllegalAccessException e) {
throw new SQLException(e.getMessage(), e);
} catch (InstantiationException e) {
throw new SQLException(e.getMessage(), e);
}
}
到这里就把对应的驱动类加载了。
由此可以得知,即使没有设置 druid.driverClassName,也会根据设置的 druid.url 来加载对应数据库的驱动的。