详解为什么Jdk旧版本加载jdbc驱动需要Class.forName 新版本的的SPI机制怎么实现

文章讲述了Java程序连接MySQL数据库时,早期如何通过Class.forName加载驱动类,以及从JDK6开始,如何利用SPI(ServiceProviderInterface)机制自动加载数据库驱动,避免手动调用Class.forName。SPI允许在运行时查找和加载实现类,MySQL驱动通过在META-INF/services下放置指定格式的配置文件,使得JVM能自动加载驱动。
摘要由CSDN通过智能技术生成

这是一个创建mysql连接的代码

Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb";
Connection connection = DriverManager.getConnection(url, "user", "pwd");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM mytable");

上面有一段Class.forName("com.mysql.cj.jdbc.Driver"),这是意味着将com.mysql.jdbc.Driver这个类加载到jvm,我们找到这个类看看。

在这个类里我们看到有个static方法,标记了static的静态代码块将会在类加载的时候执行一次,里面对这个驱动类进行了注册。那为什么项目启动的时候不会加载这个类呢?我们不是用java -cp指定了类路径吗?而我们要显示的Class.forName去加载呢?是,我们-cp可以指定类路径,但并不意味着Jvm会加载这些类,虚拟机采用的是按需加载,这是因为JVM进行类加载的时候只会加载我们使用到的类,比如我们写了个A类那他就会加载这个A类,如果A类依赖了其他的类,那就会先去加载A类所需要的其他类。所以jvm的加载的类的内存使用还是要看我们使用的类有多少。

接下来说一下为什么jdk6开始我们不用显示的Class.forName了。

首先我们了解以下SPI(Service Provider Interface)机制,它提供了一种在运行时自动查找和加载实现类的方式。通过SPI机制,开发人员可以编写接口定义,而服务提供者可以编写对这些接口的实现。然后,应用程序可以通过在Classpath中查找服务提供者实现的方式来自动加载并使用这些实现,jdk就是使用了这种spi机制帮数据库厂商进行了Class.forName,所以我们不需要再自己写了,我们来看看jdk是怎么做的。 

在rt.jar包里面的java.sql里面有个DriverManager类。

我们点进去这个方法

 然后点ServiceLoader这个类

 看到这个常量 "META-INF/services/"  ,他会去所有依赖的包里面去找这个文件夹下这个文件, 然后我们找到mysql的依赖包。

可以看到,他有个java.sql.Driver文件,这个文件名就是按照jdk给的接口Driver全类名,按照规范文件名用全类名,而文件内容就写数据库厂商自己的实现类。例如我们的mysql的实现类就是com.mysql.cj.jdbc.Driver也就是我们开头需要Class.forName需要引入的包。

接下来我们点回去ServiceLoad里面的load方法

 可以看到,里面用当前线程的上下文获取ClassLoader,因为rt.jar等核心包是通过BootstrapClassLoader去加载的,但是我们外部的jar是需要通过AppClassLoader去加载的,所以它利用这种方式就能加载到外部Jar的类。

回到这里我们点击去hasNext方法看,最终会跳到hasNextService这个方法

 这个PREFIX就是我们上面的常量了

然后hastNext获取了需要的配置信息就看看netx方法,它最终会跳到nextService方法

在这里面最终也是通过Class.forName来加载我们的驱动类的 ,这样做的好处就是以后再有一个数据库厂商需要jdk帮他加载驱动只需要实现Driver类(类名要保持一致),然后在META-INF/services/放以Driver接口为全类名,内容为实现类的全类名,这样jdk就能自动帮他加载驱动了,而不用程序员再显示调用Class.forName,这种机制在Spring的自动装配里面也是十分类似,而Spring里面是放在META-INF的spring.factorics,好了,文章就讲到这里,如有错误欢迎指出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值