博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解读MySQL驱动加载逻辑
阅读量:6421 次
发布时间:2019-06-23

本文共 3742 字,大约阅读时间需要 12 分钟。

hot3.png

解读MySQL驱动加载逻辑

我们很早之前就知道最基础的JDBC编写,先执行Class.forName方法,加载MySQL驱动。但是为什么加载过驱动后,后续的接口层的调用就会自动切换到MySQL的相关代码去执行呢?(作者:高元)

常见jdbc编写

Connection connection = null;PreparedStatement ps = null;ResultSet rs = null;try {    Class.forName("com.mysql.jdbc.Driver");    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/gdjt_db","root","root");    ps = connection.prepareStatement("select * from sys_user where id = ? ");    ps.setString(1, "1");    rs = ps.executeQuery();    while (rs.next()){        System.out.println(rs.getString("name"));    }}catch (Exception e){    e.printStackTrace();}finally {    try {        if(rs != null)rs.close();    }catch (Exception e){}    try {        if(ps != null)ps.close();    }catch (Exception e){}    try {        if(connection != null)connection.close();    }catch (Exception e){}}

当然,我们这里使用MySQL来演示,所以需要导入相关依赖

mysql
mysql-connector-java
5.1.44

以上是最简单的JDBC实现,下面我们主要查看Class.forName("com.mysql.jdbc.Driver");具体的执行逻辑。

查看第一步具体做了什么?

Class.forName("com.mysql.jdbc.Driver");
1、我们先看Class.forName
@CallerSensitivepublic static Class
forName(String className) throws ClassNotFoundException { /** 获取调用者Class */ Class
caller = Reflection.getCallerClass(); /** * 1、获取调用者的类加载器 * 2、执行类加载 * 3、执行初始化方法(initialize = true) */ return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}

具体内容见代码中的注解,可以发现,Class.forName主要就是类加载,加载了类com.mysql.jdbc.Driver

2、接着看mysql的Driver源码实现
/** * java.sql.Driver 是jdk封装的驱动接口  */public class Driver extends NonRegisteringDriver implements java.sql.Driver {    public Driver() throws SQLException {    }        /** 上一步骤类加载器加载类时,执行了初始化方法,就是执行这里的static中的代码 */    static {        try {            /** 将当前mysql的Driver注册到DriverManager中 */            DriverManager.registerDriver(new Driver());        } catch (SQLException var1) {            throw new RuntimeException("Can't register driver!");        }    }}

具体注册代码如下:

public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException {    if(driver != null) {        // 将mysql的driver封装成DriverInfo对象,并传入registeredDrivers链表中。        registeredDrivers.addIfAbsent(new DriverInfo(driver, da));    } else {        throw new NullPointerException();    }}

其中 registeredDrivers 是全局的静态变量

private final static CopyOnWriteArrayList
registeredDrivers = new CopyOnWriteArrayList<>();

这样,无论在哪里,都可以通过registeredDrivers来获取当前的驱动。

3、继续看Connection如何获取到对应的连接的
Connection conn = DriverManager.getConnection(url,username,password);

我们进入getConnection查看,代码稍微长点,不过没关系,我们只要看如下一行代码即可

private static Connection getConnection(String url, java.util.Properties info, Class
caller) throws SQLException { ... // 看到了熟悉的身影 registeredDrivers for(DriverInfo aDriver : registeredDrivers) { ... // 从registeredDrivers获取之前存入的mysql对应的Driver Connection con = aDriver.driver.connect(url, info); ... } ...}

接着执行 driver.connect( ) 方法,之前我们看过 Driver 的源码

Driver extends NonRegisteringDriver implements java.sql.Driver

所以 driver.connect 的方法,不是在 Driver 中就是在 NonRegisteringDriver 中。 结果我们在 NonRegisteringDriver 中如愿以偿的找到了connect方法(118行左右)

public Connection connect(String url, Properties info) throws SQLException {    ...    // 重要代码在这里,获取具体的连接实例    com.mysql.jdbc.Connection newConn = ConnectionImpl.getInstance(this.host(props), this.port(props), props, this.database(props), url);    return newConn;    ...}

接下来的步骤就不一一演示了。

总结

  • 通过类加载器加载Driver并初始化,将Driver添加到DriverManager的registeredDrivers中;
  • 通过registeredDrivers获取到Driver;
  • 调用Driver的connect方法,获取Mysql中的MySQLConnection;

博客

开源中国博客地址

个人博客地址

欢迎关注我的个人微信订阅号:(据说这个头像程序猿专用)

输入图片说明

转载于:https://my.oschina.net/gmarshal/blog/2239748

你可能感兴趣的文章
Gradle -help
查看>>
css3做的nav
查看>>
互联网架构师必备技术 Docker仓库与Java应用服务动态发布那些事
查看>>
Intellij IDEA 2018.2 搭建Spring Boot 应用
查看>>
SNMP AGENT函数介绍
查看>>
[Usaco2005 Open]Disease Manangement 疾病管理 BZOJ1688
查看>>
【Android视图效果】分组列表实现吸顶效果
查看>>
title: postGreSQL 插件 timescaleDB 安装使用 date: 2019-02-14 18:02:23
查看>>
并发容器与框架——并发容器(一)
查看>>
学界 | 伯克利最新研究:用算法解决算法偏差?公平机器学习的延迟影响
查看>>
多文件上传示例源码(默认支持各种类型,包括图片)
查看>>
9.2. CentOS 区域设置
查看>>
命令行基本操作学习笔记(一)
查看>>
「试着读读 Vue 源代码」工程目录及本地运行(断点调试)
查看>>
Oracle——16用户、角色和权限
查看>>
从0实现NavigationController
查看>>
A Visual Git Reference
查看>>
Tomcat 关于表单提交数据量过大导致数据丢失的问题
查看>>
gitlab hook declined错误
查看>>
金融数据库
查看>>