IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> JDBC - 为什么不需要手动加载 Driver 实现类了 -> 正文阅读

[大数据]JDBC - 为什么不需要手动加载 Driver 实现类了

JDBC - 为什么不需要手动加载 Driver 实现类了

未经允许不得转载!

看到别人说的不对或者不全,所以开篇文章补充下。

如果只是简单使用 JDBC,那么直接按下面这样做就行了:

// 实例化 MySQL 的 Driver 实现类
java.sql.Driver driver = new com.mysql.cj.jdbc.Driver();
// 建立连接
Connection connect = driver.connect(url, properties);
// ... 各种操作

上面这种做法耦合性太强了,如果MySQL的 jdbc Driver 实现类变了呢?手动改呗!
那么如果需要同时使用多个不同的数据库呢?

所以 java 提供了一个简单的 jdbc Drivers 管理类:java.sql.DriverManager
通过java.sql.DriverManager#registerDriver()注册上面例子的实例
通过java.sql.DriverManager#getConnection()建立上面例子中的数据库连接
通过java.sql.DriverManager#getDrivers()方法获取所有注册的示例
…更多方法自己看

也就是说只要调用DriverManager#registerDriver()就可以把实例注册进去,然后通过java.sql.DriverManager#getConnection()获取连接(只有一个实例或者第一个注册的实例就是所需的),如果有多个,则通过java.sql.DriverManager#getDrivers()获取所有的实例,然后自己选择需要的 Driver 实例,然后调用 connect 方法建立连接。

那么问题就来了,你们在使用 jdbc 的时候有写过DriverManager#registerDriver()这样的代码吗?

先看看远古时期使用 jdbc 的5步走是怎么做的吗?(远古时期:java1.2+ 包括)

  • 1/5 Class.forName(driver 实现类的全名);
  • 2/5 建立连接 Connection
  • 3/5 获取 Statement
  • 4/5 执行并获取 ResultSet
  • 5/5 关闭资源
// jdbc 1/5 Class.forName(driver 实现类的全名);

final String MYSQL_DRIVER = "com.mysql.jdbc.Driver";
final String MYSQL_NEW_DRIVER = "com.mysql.jdbc.Driver";

// 方式1,显式手动单独加载两个 jdbc 实现类
Class<?> driverImplClass1 = Class.forName(MYSQL_DRIVER);
Class<?> driverImplClass2 = Class.forName(MYSQL_NEW_DRIVER);
// ... more

// 方式2,隐式手动批量加载多个 jdbc 实现类
 多个驱动实现类用":"隔开
String DRIVERS = MYSQL_DRIVER + ":" + MYSQL_NEW_DRIVER;
String defaultDrivers = System.getProperty("jdbc.drivers");
if (defaultDrivers == null || defaultDrivers.length() == 0) {
    System.setProperty("jdbc.drivers", DRIVERS);
}
else {
    // 合并后再设置配置
}

1/5只是加载了类,所以 Driver 实现类的静态代码块(或者有静态字段)很重要。
以MySQL 5.1.48 的 Driver 实现类com.mysql.jdbc.Driver为例:

// 去掉了一些不重要的代码和注释
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
    		// 看到了没有,看到了没有,看到了没有 重要的事情说三遍
            java.sql.DriverManager.registerDriver(new Driver());
    }
    public Driver() throws SQLException {}
}
public class NonRegisteringDriver implements java.sql.Driver {
    static {
    		// AbandonedConnectionCleanupThread 这个类不用看
    		// 简单说就是启动一个守护线程去跟踪被垃圾回收器回收的 Connection
    		// 如果资源没有关闭则进行相关操作,从而节约资源以及防止异常情况发生
            Class.forName(AbandonedConnectionCleanupThread.class.getName());
    }
}

再看看现代是如何注册 Driver 实现类的?(现代:java1.6+ 包括)
要说起这个得先说起java.sql.DriverManager这个类,这个类在被加载时,会执行DriverManager#loadInitialDrivers()方法,而远古时代提供的批量注册 Driver 实现类的方式就是在这里面实现的,代码很简单不说了。
这里重点说下另外的一个方式,也就是包含ServiceLoader.load(Driver.class)代码的那一整块,这块代码是根据 java 6 提供的 SPI 功能而增加的:

  1. 在项目下提供一个META-INF/services/java.sql.Driver文件,可以参考 MySQL 的那个实现
  2. 调用ServiceLoader.load(Driver.class);获取 service,此时资源还未被加载(因为是懒加载的)
  3. 通过迭代器进行遍历 (java.util.ServiceLoader.LazyIterator),迭代器在执行next方法的时候最终会调用nextService方法,然后加载类,然后实例化。

完结撒花

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:44:36  更:2021-09-22 14:47:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:28:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码