可以同时加载两个mysql驱动吗_漫谈SPI机制以及数据库驱动加载

本文介绍了Java SPI服务发现机制,通过分析MySQL驱动加载过程,解释了使用SPI的原因和优势。SPI允许动态查找接口实现类,而传统方式则是硬编码。文章详细探讨了SPI配置文件加载、数据库驱动加载流程,并揭示了SPI如何打破双亲委派模型。
摘要由CSDN通过智能技术生成

介绍

SPI是一种服务发现机制,允许jdk从ClassPath:META-INF/services查找接口实现类实例化到内存中。

非SPI的加载方式则需要用户在代码中指定接口实现类并进行实例化。

为何要用SPI?

实际上传统的服务加载方式从代码量来说并不会比SPI多上多少,但从java设计上考虑,传统的加载方式是一种硬编码的编程方式,而SPI设计的初衷就是将服务的加载从代码中剥离出去使得我们编程的时候,不需要考虑服务的选择,直接面向接口编程。

我们以mysql驱动的加载来演示加载方式的区别

//传统加载方式 1
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:33061/xxx?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull", "root", "123456");

//传统加载方式 2
System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:33061/xxx?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull", "root", "123456");

//SPI加载方式
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:33061/xxx?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull", "root", "123456");

强调

两种加载方式没有谁对谁错,编程思想仁者见仁智者见智,如果不能理解设计者的想法,请记住它。

SPI配置文件加载函数介绍

举个例子:

//摘自源码
//大体看了下load方法对ServiceLoader类的类加载器、上下文等变量进行初始化,并且校验了Driver.class,实例化了一个私有迭代器LazyIterator对象保存需要加载的服务接口,并未做任何查找操作或者实例化操作
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
while(driversIterator.hasNext()) {
    driversIterator.next();
}

这段代码会在classpath路径下的META-INF/services目录找到文件名为java.sql.Driver的文本并读取其中的内容(每一行都是一个实现类的权限命名),挨个实例化其实现类 如图:

94fdeaecaaa25d5a550a7272e503b2db.png

(lib目录在classpath下)

浅析SPI机制下数据库驱动加载过程(以mysql为范例)

DriverManager有一个初始化的静态块,这会在执行getConnection前运行

static {
        //初始化驱动
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
    }

查看loadInitialDrivers()

//以下代码删除源码注释减少篇幅
private static void loadInitialDrivers() {
        //这里drivers的获取对应我提到的 传统加载方式 2
        String drivers;
        try {
            drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });
        } catch (Exception ex) {
            drive
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值