【Druid源码阅读】7. 驱动加载

11 篇文章 0 订阅

在初始化 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 来加载对应数据库的驱动的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值