浅谈Class.forName()在JDBC中的作用

2023-11-16

目录

1、Class.forName()有什么作用呢?

2、为什么不直接new?

3、为什么删除Class.forName("com.mysql.jdbc.Driver")还是可以运行?


JDBC是Bridge模式的典型应用,DriverManager就是其中的Abstraction;java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现。前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。 Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的。

一般,我们在连接数据库时,会使用如下的代码:

try {
    Class.forName("com.mysql.jdbc.Driver");
    connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
} catch (Exception e) {
    e.printStackTrace();
}

1、Class.forName()有什么作用呢?

首先,我们都知道,在java中Class.forName()方法在java中的作用是1、用于在JVM中查找并加载指定的类到内存中。2、初始化这个类

此时,我们将"com.mysql.jdbc.Driver"作为参数传入,是让JVM到"com.mysql.jdbc"路径下,找到Driver类并将其加载到内存中。

我们一起来看一下Driver类的详细代码:

public class Driver extends NonRegisteringDriver
  implements java.sql.Driver
{
  public Driver() throws SQLException{
  }
​
  static
  {
    try
    {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

Class.forName(“com.mysql.jdbc.Driver”)的作用实际上就是调用DriverManager的 registerDriver方法注册一个mysql的JDBC驱动(Driver)而已(简而言之,就是将mysql驱动注册到DriverManager中去)。

其中调用的DriverManager的 registerDriver方法中的关键代码有:

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

它的底层利用了一个CopyOnWriteArrayList作为容器(这是一个线程安全的容器,不过每次add的时候都会对底层数组进行一次新的复制,所以在读远多于写的时候建议可以使用这个),放那些注册进去的DriverInfo。最终getConnection(...)的时候就拿registerDrivers里面注册进去的具体的某个数据库的DriverInfo(像MySql的Driver就在DriverInfo里面)去连接具体的数据库。

整个流程就是:

JDK不负责和数据库连接打交道,也没必要,只提供一个具体的接口Driver,告诉所有第三方,要连接数据库,就去实现这个接口,然后通过DriverManager注册一下,到时候连接某个数据库的时候,你已经在我这里注册了,我会调用你注册进来的Driver里面的方法去对指定数据库进行连接的。然后Mysql就实现自己的Driver,Oracle就实现自己的Driver,通过static块注册一下,再然后,就没有然后了。

这样之后,我们就可以通过DriverManager的getConnection方 法获得mysql的连接了:

connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/test"
, "root", "root");

到此为止,我们就获得了connection对象,现在就可以对数据库进行操作了。

总而言之,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。

2、为什么不直接new?

意思是这么写"com.mysql.jdbc.Driver d = new com.mysql.jdbc.Driver();",这样写也是可以的,因为在new的时候会自动触发对一个类的初始化。

但问题是new出来干嘛?com.mysql.jdbc.Driver里面的方法我们会用到吗,并且我们知道怎么用吗?仅仅为了初始化一个类而new一个类实例出来还不如不去new,直接使用Class.forName(String name)初始化就可以了。DriverManager类的getConnection(...)方法的存在本身就是帮助用户调用Driver里面的各种方法连接数据库,JDK都做好了,开发者就没必要自己写了。

特别要注意的是,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。

com.mysql.jdbc.Driver driver = null;
//or:    
ClassLoader cl = new ClassLoader();   
cl.loadClass("com.mysql.jdbc.Driver");  

3、为什么删除Class.forName("com.mysql.jdbc.Driver")还是可以运行?

1996年1月23日JDK1.0发布,Java语言有了第一个正式版本的运行环境。JDBC是1997年2月19日,在JDK1.1的版本中发布的,从版本就看得出,JDBC属于Java技术的一些最基础的功能点。那在JDK1.5之后,其实已经不需要去显式调用Class.forName("com.mysql.jdbc.Driver")了,DriverManager会自动去加载合适的驱动,但是前提是CLASSPATH下必须有驱动jar包

在DriverManager的源码中可以看到一个静态块:

 /**
     * Load the initial JDBC drivers by checking the System property
     * jdbc.properties and then use the {@code ServiceLoader} mechanism
     */
    static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

进入loadInitialDrivers()方法中看到以下一段代码:

private static void loadInitialDrivers() {
         String drivers;
         try {
             drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                 public String run() {
                     return System.getProperty("jdbc.drivers");
                 }
             });
         } catch (Exception ex) {
             drivers = null;
         }
         // If the driver is packaged as a Service Provider, load it.
         // Get all the drivers through the classloader
         // exposed as a java.sql.Driver.class service.
         // ServiceLoader.load() replaces the sun.misc.Providers()
 
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
 
                 ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                 Iterator<Driver> driversIterator = loadedDrivers.iterator();
 
                 /* Load these drivers, so that they can be instantiated.
                  * It may be the case that the driver class may not be there
                  * i.e. there may be a packaged driver with the service class
                  * as implementation of java.sql.Driver but the actual class
                  * may be missing. In that case a java.util.ServiceConfigurationError
                  * will be thrown at runtime by the VM trying to locate
                  * and load the service.
                  *
                  * Adding a try catch block to catch those runtime errors
                  * if driver not available in classpath but it's
                  * packaged as service and that service is there in classpath.
                  */
                 try{
                     while(driversIterator.hasNext()) {
                         driversIterator.next();
                     }
                 } catch(Throwable t) {
                 // Do nothing
                 }
                 return null;
             }
         });

重点是这句代码:

ServiceLoader.load(Driver.class);

这行代码可以把类路径下所有jar包中META-INF/services/java.sql.Driver文件中定义的类加载上来,此类必须继承自java.sql.Driver。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈Class.forName()在JDBC中的作用 的相关文章

随机推荐

  • 一些官方的github地址

    阿里巴巴开源github地址 https github com alibaba 腾讯开源github地址 https github com Tencent 奇虎360github地址 https github com Qihoo360 小米
  • xss的绕过方式

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 xss的类型以及常用标签 二 xss常用绕过 总结 前言 xss cross site scripting 中文 跨站脚本攻击 常年位于owasp top
  • 损失函数和正则化

    参考 https www cnblogs com LXP Never p 10918704 html https blog csdn net Heitao5200 article details 83030465 https zhuanla
  • C++-----拷贝构造函数

    拷贝构造函数是一种特殊的构造函数 和构造函数同样是特殊的类成员函数 C 提供的拷贝构造函数用于在建立新对象时将已存在对象的数据成员的值复制给新对象 拷贝函数的特点 拷贝函数是构造函数的一个重载形式 拷贝函数的参数只有一个且必须是类类型对象的
  • ffmpeg命令使用记录

    1 添加水印 ffmpeg i a mp4 acodec copy b v 548k vf movie logo png watermark in watermark overlay 20 20 output mp4 说明 i a mp4
  • TM4C123库函数学习(1)--- 点亮LED+TM4C123的ROM函数简介+keil开发环境搭建

    前言 1 首先 我们需要知道TM4C123是M4的内核 对于绝大多数人而言 入门都是学习STM32F103 这款芯片是采用的M3的内核 所以想必各位对M3内核还是有一定的了解 M4内核就是M3内核的升级版本 他继承了M3的的所有功能 同时还
  • leetcode 1604. 警告一小时内使用相同员工卡大于等于三次的人

    力扣公司的员工都使用员工卡来开办公室的门 每当一个员工使用一次他的员工卡 安保系统会记录下员工的名字和使用时间 如果一个员工在一小时时间内使用员工卡的次数大于等于三次 这个系统会自动发布一个 警告 给你字符串数组 keyName 和 key
  • C~运算符

    运算符是一种告诉编译器执行特定的数学或逻辑操作的符号 C 语言提供了以下类型的运算符 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 算术运算符 下表显示了 C 语言支持的所有算术运算符 假设变量 A 的值为 10 变
  • Windows10安装Docker(基于WSL2,包含WSL2安装教程)

    WSL2 wsl是windows自带的功能 只需要开启Windows功能即可安装子系统 可以通过以下命令获取发行版名字 wsl list online 通过以下命令安装 wsl install d 发行版名字 如 wsl install d
  • android input 机制源码分析

    具体文字说明请参考 http blog csdn net luoshengyang article details 6882903
  • 2018年AI趋势盘点(02)

    善用智能之道 请您点击上方蓝色字体 欢迎关注 九三智能控 懒人阅读 2017年被定义为AI的史诗年 九三觉得17年确实引爆了AI 同时泡沫也存在不少 18年的AI将更加务实技术更加接近真实场景 可以确认的一点是 认知决策能力的升级将对所有行
  • WiFi探针的工作原理及采集的数据?

    WiFi探针在商业 公共安全领域的大放异彩 更多的人想了解什么是WiFi探针 WiFi探针是怎么工作的 WiFi探针的工作原理 要深入了解WiFi探针技术 首先先认识WiFi使用的网络协议 WiFi采用的是IEEE802 11协议集 此协议
  • element对上传组件二次封装,vue上传下载组件的实现

    前言 对element的上传组件进行二次封装 让他可以实现上传下载功能 实现效果 手动上传 不是自动 选中文件后可上传 也可清空选中文件 单个删除也是可以的 实现步骤 1 封装好的 uploadAndDown vue源码 引入就好
  • Linux 入门常用命令(ZT)

    1 Linux进入与退出系统 进入Linux系统 必须要输入用户的账号 在系统安装过程中可以创建以下两种帐号 1 root 超级用户帐号 系统管理员 使用这个帐号可以在系统中做任何事情 2 普通用户 这个帐号供普通用户使用 可以进行有限的操
  • MATLAB——求冲激响应和阶跃响应

    题目 已知一个RLC串联振荡电路系统函数为 其中L 22mH C 2000pF R 100 求其时域的冲激响应和阶跃响应 代码解释 这段代码定义了三个变量 电感L 电容C和电阻R 然后 定义了两个数组a和b 它们是差分方程的系数 接下来 使
  • 拿不到年薪25W全额退款

    速报 2023年经济下行趋势明显 毕业生出路在哪儿 今年 毕业人数将达到1158万 导致很多公司招聘非常谨慎 要求也变得非常更高 别说offer 现在出门找个实习都难 大学四年我都学了啥 是啊 现在咋找实习丰富简历啊 今年毕业的我该怎么办
  • selenium自动处理验证码

    自动化测试中的验证码处理方法小总结 转自 Selenium中文论坛 gt Selenium RC gt 转 自动化测试中的验证码处理方法小总结 原作者 yanpingsha 目前 不少网站在用户登录 用户提交信息等登录和输入的页面上使用了验
  • kubernetes ——网络存储nfs

    kubernetes 网络存储nfs 一 共享的机器上安装nfs 1 yum y insstall nfs utils 2 mkdir p etc exports 3 vi etc exports ifs kubernetes rw no
  • 恶意代码分析实战——Lab03-01.exe基础动态分析篇

    恶意代码分析实战 Lab03 01 exe基础动态分析篇 1 实验目的 综合运用各种分析工具 分析Lab03 01 exe的基本信息 并推测其功能 2 实验环境 硬件 软件 VMware虚拟机 winxp 硬件 处理器Intel Core
  • 浅谈Class.forName()在JDBC中的作用

    目录 1 Class forName 有什么作用呢 2 为什么不直接new 3 为什么删除Class forName com mysql jdbc Driver 还是可以运行 JDBC是Bridge模式的典型应用 DriverManager