现在大家连数据库估计已经很少用JDBC了,我也是最近发现在JDBC4.0以后(对应JDK7+),JDBC不用写Class.forName了。这时候就要扯进来一个技术——SPI(Service Provider Interface)。它是用来动态实现接口的。而在JDK中典型的用到该技术的,就是JDBC了。
现在JDBC获取连接如下:
Connection connection = DriverManager.getConnection("http://url", "username", "pwd");
跟进DriverManager.class,有一段static代码:
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
在java.sql.DriverManager#loadInitialDrivers
中,有下面一句话:
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
从这句话就会加载出N多的Driver,你所添加的都有。
本次测试使用的mysql的jar,mysql的原来的classForName是com.mysql.jdbc.Driver
,跟进此类,发现在此类的jar下有一文件夹:META_INF/services
,内有一文件java.sql.Driver
。这个文件名正好是上面load方法中Driver的全路径名。
这个也是一个类,其唯一实现是com.mysql.jdbc.Driver
类。
由此我们可以理出,SPI就是在根目录下,建一文件夹META_INF/services
,你想动态加载什么接口将某接口的全路径名称定义为一文件名,内部每一行写一个实现类的全类名。然后在加载时会将该文件中所有的类都加载进去。
该功能旨在统一不同厂商的不同实现,A制定标准,其他采用A方案者进行实现他自己的内容,A只需要在指定地方加载某些实现的文件即可。
该功能在Spring 和dubbo 中,有注解@SPI,在spring boot中体现为自动装配。
网友评论