zoukankan      html  css  js  c++  java
  • JDBC自动加载驱动的SPI机制

    本人试验无意间发现,只要前面pom引入了mysql-connector-java这个包,什么都不写也会加载mysql数据库驱动, (当然如果不引入mysql-connector-java这个包是不行的)这是为什么呢?

    一 为什么java不加载驱动可以

    源码包里DriverManager类上面说明了,不加载也可以的注释。

     * <P>Applications no longer need to explicitly load JDBC drivers using <code>Class.forName()</code>. Existing programs
     * which currently load JDBC drivers using <code>Class.forName()</code> will continue to work without
     * modification.
    翻译过来:

       * <P>应用程序不再需要使用<code> Class.forName()</ code>显式加载JDBC驱动程序。 现有程序
       * 当前使用<code> Class.forName()</ code>加载JDBC驱动程序将继续工作而无需
       * 修改。

    原来在新版本的JDBC中不用在通过Class.forName()来显示加载JDBC驱动,那到底是怎么实现的呢,我们来看下源码。

    二 源码分析

    下面是引入的mysql-connector-java包

        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.11</version>
        </dependency>
    public static void insertData() {
            private String URL = "jdbc:mysql://localhost:port/databaseName?useUnicode=true&characterEncoding=UTF-8";
            private String USER = "xx";
            private String PASSWORD = "xx";
           
                          //1 加载数据库驱动
            Connection connection = DriverManager.getConnection(URL,USER,PASSWORD); //    2 获取链接connection
            PreparedStatement preparedStatement = connection.prepareStatement("insert into test (name, sex) values (?,?)"); // 3 通过statement对象执行sql
            preparedStatement.setString(1, "xx");
            preparedStatement.setString(2, "yy");
            Boolean result = preparedStatement.execute();      // 4 获取返回结果
        }

    启动服务后,执行静态方法DriverManager.getConnection 因为需要加载DriverManager类,所以执行static静态代码块。

     在java这头定义了一个Driver接口,ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class),那么ServiceLoader.load()方法是干什么的呢?

    在ServiceLoader.load时,根据传入的接口类,遍历META-INF/services目录下的以该类命名的文件中的所有类,并实例化返回。ServiceLoader是spi机制的一个实现

    具体可以参加ServiceLoader类的源代码如下图,PREIX是META-INF/services,service.getName是接口Driver的类名称,拼接出文件路径:

     拼出的全路径fullName是:META-INF/services/java.sql.Driver,然后去本地找到该路径下的这个文件,然后把这个文件加载进来,这个文件的内容如下

     文件内容是:com.mysql.cj.jdbc.Driver,这个类就是mysql厂商提供的驱动里面的Driver实现类,然后对其进行初始化加载,进行实例化,调这个类的static静态块,执行注册驱动。

      

    三 SPI机制总结

    ServiceLoader是SPI的是一种实现,SPI,全称Service Provider Interface,用于一些服务提供给第三方实现或者扩展,可以增强框架的扩展或者替换一些组件。 通过jar包来实现扩展功能的热插拔。

  • 相关阅读:
    [转]:Android 5.0的调度作业JobScheduler
    Android 移动端数据结构
    算法-二分查找
    设计模式-设计原则
    设计模式-单例模式(Singleton Pattren)(饿汉模式和懒汉模式)
    Android 7.0 Dialog 无法显示的问题
    设计模式-装饰模式(Decorator Pattern)
    产品中心2
    java中static和final修饰符
    java访问修饰符
  • 原文地址:https://www.cnblogs.com/wanghongsen/p/12620168.html
Copyright © 2011-2022 走看看