栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDBC和SPI

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDBC和SPI

Class.forName做了什么

我们在用JDBC的时候,总是会写一句

Class.forName("com.mysql.cj.jdbc.Driver");

这里以mysql驱动为例,其他驱动都类似。
这一步会使用类加载器加载对应的驱动,并执行com.mysql.cj.jdbc.Driver的静态代码块。

进入com.mysql.cj.jdbc.Driver
静态代码块中完成了驱动的注册,也就是new了一个自身的实例,并注册到DriverManager中

DriverManager.registerDriver(new Driver());

进入DriverManager类,registerDriver方法
registeredDrivers是一个CopyOnWriteArrayList,保存所有注册过的驱动

registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
DriverManger.getConnection是怎么获取连接的

DriverManger类的getConnection方法
遍历驱动list,逐个执行connect方法,如果非空,返回当前connection。

for(DriverInfo aDriver : registeredDrivers) {
  try {
           Connection con = aDriver.driver.connect(url, info);
           if (con != null) {
               return (con);
           }
       } catch (SQLException ex) {
           if (reason == null) {
               reason = ex;
           }
       }
 }
JDBC和SPI

如果去掉Class.forName,程序也能正常运行(JDBC4以后)。
首先看mysql驱动的jar包,meta-INF/services下有个文件,文件名是java.sql.Driver,文件内容是com.mysql.cj.jdbc.Driver。
再看DriverManager类的静态代码块,调用了loadInitialDrivers方法。

static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

进入loadInitialDrivers方法
使用ServiceLoader去加载驱动类

AccessController.doPrivileged(new PrivilegedAction() {
      public Void run() {
          ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);
          Iterator driversIterator = loadedDrivers.iterator();
          try{
              while(driversIterator.hasNext()) {
                  driversIterator.next();
              }
          } catch(Throwable t) {
          // Do nothing
          }
          return null;
      }
  });
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/685779.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号