SPI-数据库驱动的实现过程

本文介绍 Hikari 数据源如何通过 SPI 机制加载数据库驱动。在调用 getConnection 方法时,Hikari 会实例化 HikariPool 对象,并通过 DriverDataSource 初始化数据源。在此过程中,会调用 DriverManager 的 getDrivers 方法来获取已注册的驱动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文基于jdk1.8
前文介绍了SPI的实现原理,本篇主要看下,项目中数据库驱动对SPI的使用。
以数据源Hikari为例。
数据源调用getConnection方法时,会实例HikariPool对象,跟着调用链,最终会调用DriverManager.getDrivers。

public class HikariDataSource extends HikariConfig implements DataSource, Closeable {

	public Connection getConnection() throws SQLException {
            ...
            HikariPool result = this.pool;
            if (result == null) {
                synchronized(this) {
                    result = this.pool;
                    if (result == null) {
						...
                            this.pool = result = new HikariPool(this);
                        ...
                    }
                }  
        	...
    }
}
public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateListener {
	public HikariPool(HikariConfig config) {
        super(config);
        ...
    }
}
abstract class PoolBase {
	PoolBase(HikariConfig config) {
        ...
        this.initializeDataSource();
    }
}
abstract class PoolBase {
	PoolBase(HikariConfig config) {
        ...
        this.initializeDataSource();
    }

	 private void initializeDataSource() {
        ...
         if (jdbcUrl != null && dataSource == null) {
            dataSource = new DriverDataSource(jdbcUrl, driverClassName, dataSourceProperties, username, password);
        }
          ....
    }
}
abstract class PoolBase {
	PoolBase(HikariConfig config) {
        ...
        this.initializeDataSource();
    }

	 private void initializeDataSource() {
        ...
         if (jdbcUrl != null && dataSource == null) {
            dataSource = new DriverDataSource(jdbcUrl, driverClassName, dataSourceProperties, username, password);
        }
          ....
    }
}
public final class DriverDataSource implements DataSource {
	public DriverDataSource(String jdbcUrl, String driverClassName, Properties properties, String username, String password) {
		... 
        if (driverClassName != null) {
        	// 调用 DriverManager 方法
            Enumeration drivers = DriverManager.getDrivers();
           ...
        }   
        ...
    }
}

调用getDrivers前,首先执行静态代码块的内容,此处就是执行SPI的关键

public class DriverManager {
	 static {
        loadInitialDrivers();
    }
}
private static void loadInitialDrivers() {
        String drivers;
        	// 这里首先判断环境变量中有没有指定驱动类
            drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });

        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
				// 这里执行SPI操作
                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator<Driver> driversIterator = loadedDrivers.iterator();
                try{
                	// 实例化驱动实现类
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                }
                return null;
            }
        });
		... 
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值