本文基于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;
}
});
...
}