SPI在JDBC中的运用
前言
之前学习了JDK SPI的机制,本文专门讨论2个内容:
1.为什么在使用SPI后,不需要Class.forName()了?
2.SPI在JDBC中的运用。
JDBC模板代码
private static final String URL = "jdbc:mysql://localhost:3306/demo?useSSL=true&useUnicode=true&characterEncoding=UTF-8";
private static final String DRIVER = "com.mysql.jdbc.Driver";
//加载驱动信息,使用SPI之后,不需要下面这行代码了。
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Connection conn = DriverManager.getConnection(url, user, password);
String sql = "insert into user (name, pwd) values(?,?)";
Statement st = conn.createStatement();
st.executeQuery(sql);
}
为什么在使用SPI后,不需要Class.forName()了?
首先我们需要了解:Class.forName("com.mysql.jdbc.Driver")的作用是:
根据JVM类加载的原理,该代码会将这个字节码文件加载到虚拟机内部,
而由于类加载共有7个阶段,并且Class.forName()方法中使用了JDK反射包中Class<?> caller = Reflection.getCallerClass();
所以,Class.forName()方法不仅仅会加载Driver类,还会执行它的类初始化的过程(即静态代码块,静态变量赋值等操作)
其次我们看看为什么不需要Class.forName()了?
我们来分析一下main方法中的第一句源码:Connection conn = DriverManager.getConnection(url, user, password);
首先调用该方法前,JVM会加载DriverManager类,然后执行连接,初始化。
DriverManager.Class源码
/**
* Load the initial JDBC drivers by checking the System property
* jdbc.properties and then use the {@code ServiceLoader} mechanism
* 这里清楚的说明了,该代码块会使用SPI机制进行服务发现。
*/
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
然后跟踪代码loadInitialDrivers();会发现:
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
/*
* 省略注释
*/
try{
while(driversIterator.hasNext()) {
driversIterator.next();
}
} catch(Throwable t) {
// Do nothing
}
我的上一篇博客JDK中的SPI机制中的例1和这里是一样的,因为我本来也是参考它来学习的。
根据上一篇博客里面的类加载分析,我们知道了这里DriverManager.Class的静态初始化,和显示的执行Class.forName()是一致的。
因为他们使用的类加载器分别是:
1.DriverManager.Class静态初始化内的SPI机制所使用的是:线程上下文类加载器,默认为系统类加载器AppClassLoader。
2.Class.forName()为main方法所在的类的类加载器:系统类加载器AppClassLoader。
所以这里默认是同一个类加载器来加载我们classpath下面的com.mysql.jdbc.Driver。
综上:
1.在使用SPI后,不需要显示调用Class.forName()了。
2.SPI在JDBC中的运用就是如此,它使用了SPI来对实现方做了约束,并把实现独立于实现方中,JDK这样来提供了一种服务提供发现机制.
SPI在JDBC中的运用的更多相关文章
- JDBC中的Statement和PreparedStatement的区别
JDBC中的Statement和PreparedStatement的区别
- [转]JDBC中日期时间的处理技巧
Java中用类java.util.Date对日期/时间做了封装,此类提供了对年.月.日.时.分.秒.毫秒以及时区的控制方法,同时也提供一些工具方法,比如日期/时间的比较,前后判断等. java.uti ...
- JDBC中的事务-Transaction
事务-Transaction 某些情况下我们希望对数据库的某一操作要么整体成功,要么整体失败,经典的例子就是支付宝提现.例如我们发起了支付宝到银行卡的100元提现申请,我们希望的结果是支付宝余额减少1 ...
- Oracle数据库编程:在JDBC中应用Oracle
9.在JDBC中应用Oracle: JDBC访问数据库基本步骤: 1.加载驱动 2.获取链接对象 3.创建SQL语句 4.提交S ...
- JDBC中的ResultSet无法多次循环的问题。
前几天碰见了一个很奇葩的问题,使我百思不得其解,今天就写一下我遇见的问题吧,也供大家参考,别和我犯同样的毛病. 首先说下jdbc,jdbc是java是一种用于执行SQL语句的Java API,从jdb ...
- 在JDBC中使用Java8的日期LocalDate、LocalDateTime
在实体Entity里面,可以使用java.sql.Date.java.sql.Timestamp.java.util.Date来映射到数据库的date.timestamp.datetime等字段 但是 ...
- 使用JDBC中的出现的乱码和查询无结果问题
使用JDBC中的问题 连接的后出现查询结果是乱码. 1.可能是代码的编码与数据库的编码不同 有可以将二者都设置为UTF-8 2.如果比较懒得话可以只设代码为UTF-8 mysql 连接url中us ...
- 转:JDBC中关于PreparedStatement.setObject的一些细节说明
原文地址:https://blog.csdn.net/zhiyangxuzs/article/details/78657235 JDBC中PreparedStatement.setObject(ind ...
- 一、DAO设计模式 二、DAO设计模式的优化 三、JDBC中的事务,连接池的使用
一.DAO设计模式概述###<1>概念 DAO,Data Access Object ,用于访问数据库的对象. 位于业务逻辑和数据持久化层之间,实现对数据持久化层的访问 ...
随机推荐
- 从零开始实现简单 RPC 框架 8:网络通信之 Request-Response 模型
Netty 在服务端与客户端的网络通信中,使用的是异步双向通信(双工)的方式,即客户端和服务端可以相互主动发请求给对方,发消息后不会同步等响应.这样就会有一下问题: 如何识别消息是请求还是响应? 请求 ...
- hyperf从零开始构建微服务(一)——构建服务提供者
阅读目录 什么是服务 构建服务提供者 1.创建数据表 2.构建服务提供者 3.安装json rpc依赖 4.安装rpc server组件 5.修改server配置 6.配置数据库 7.编写基础代码 7 ...
- Linux从头学11:理解了这三个概念,才能彻底理解任务管理和任务切换
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- Kubernetes环境Traefik部署与应用
本作品由Galen Suen采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可.由原作者转载自个人站点. 概述 本文用于整理基于Kubernetes环境的Traefik部署与应用, ...
- go中语句为什么不用加分号;结束
不用人加 编译的时候自动加了分号; 编译器工作原理 首先,在一行中,寻找成对的符号,比如一对字符串的引号.一对圆括号,一对大括号 上述任务完成后,在一行中没有其他成对的标示,然后就在行尾追加分号; 所 ...
- Windows phone 8 触发器使用小结
引用空间: xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expres ...
- 企业级镜像仓库 harbor
企业级镜像仓库 harbor 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:跨 Docker 宿主机网络 overlay 类型 h ...
- 安卓开发 利用百度识图api进行物体识别
前文 之前的随笔中,已经通过相机或相册获取到了我们想要的图片,接下来进行识图api的配置工作.我使用的是百度的api,利用python获取信息,并在MainActivity中进行调用来输出信息. 一. ...
- POJ题目 1003Hangover(叠放纸牌)
POJ 1003 叠放纸牌 描述 您可以将多张纸牌悬在桌子上多远?如果您有一张卡,则可以创建一个最大长度为卡长的一半.(我们假设这些卡片必须垂直于桌子.)使用两张卡片,您可以使最上面的卡片悬垂在底部的 ...
- 【PHP数据结构】树和二叉树
树的概念其实非常地广泛,也非常地常见,大家见到这个词千万不要惊慌,因为真的每天你都能见到树结构在我们生活中的应用.比如说公司的组织结构: 另外像我们家里的族谱,或者说是我们的家庭结构,也是一个典型的树 ...