SPI机制
大约 1 分钟数据库技术JDBC
连接获取源码分析
关键代码在 DriverManager.getConnection()
@Test
public void test3() throws SQLException {
// 1.定义要素
String url = "jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf8&&useSSL=false&serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
// 4.获取连接
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println(connection);
}
查看源码(JDK8)
DriverManager
类有静态代码块,加载驱动就在这里:
/**
* Load the initial JDBC drivers by checking the System property
* jdbc.properties and then use the {@code ServiceLoader} mechanism
*/
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}

当MySQL的驱动被SPI加载到jvm中之后,就会被注册到DriverManager。

public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}

获取连接


简单使用SPI
JDK在项目启动的时候,会到
META-INF/services/
加载文件,文件名就是接口,内容是接口的实现类。SPI会通过工具类ServiceLoader
反射把接口的实现类加载到JVM中。
Animal接口
public interface Animal {
}
Ca和Dog实现类
public class Cat implements Animal{
}
public class Dog implements Animal{
}
META-INF/services/com.sanfen.Animal
com.sanfen.Cat
com.sanfen.Dog
使用ServiceLoader加载实现类:
public class Client {
public static void main(String[] args) {
ServiceLoader<Animal> loadedDrivers = ServiceLoader.load(Animal.class);
Iterator<Animal> driversIterator = loadedDrivers.iterator();
while (driversIterator.hasNext()){
Animal animal = driversIterator.next();
System.out.println(animal);
}
}
}
结果:
com.sanfen.Cat@45ee12a7
com.sanfen.Dog@330bedb4
Process finished with exit code 0
我们并没有创建Cat和Dog对象,是ServiceLoader加载配置文件,通过反射创建的。我们只是传入了接口
Animal.class
。SPI(Service Provider Interface)会自己去对应位置加载解析文件。