不久前,我还在实现JDBC驱动程序。但在开始工作之前,我研究了一些MySQL JDBC驱动源,发现它们包含两个java.sql.Driver
接口的实现:com.mysql.jdbc.Driver和com.mysql.jdbc.NonRegisteringDriver,其中Driver
也扩展了NonRegisteringDriver
。Driver
类只包含调用DriverManager.registerDriver()
来注册类的静态块:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
而
NonRegisteringDriver
实现了所有的java.sql.Driver
接口方法。我的第一个想法是,通过这样实现一个驱动程序,MySQL驱动程序的开发人员正在遵循java.sql.Driverguidlines,该guidlines声明如下:
强烈建议每个驱动程序类都应该小而独立,这样就可以加载和查询驱动程序类,而不必引入大量的支持代码。
但是,如果我正确理解Java类加载,那么拥有单独的
com.mysql.jdbc.Driver
类绝对没有意义,因为它的父类和所有实现代码都将在执行静态块之前加载。我是不是丢了什么东西?
最佳答案
不,实际上如果没有com.mysql.jdbc.Driver
类,JDBC驱动程序的当前实现将不能满足mysql
协议,这claims:
加载驱动程序类时,它应创建
自己注册给司机经理。这意味着用户可以通过调用
Class.forName("foo.bah.Driver")}
java.sql.Driver
类不包含创建和注册自实例的这一部分。为什么
com.mysql.jdbc.NonRegisteringDriver
开发人员决定将实现本身与本质上注册其实例的类区分开来?很难说清楚,但如果他们决定在同一个包中提供多个实现,这可能会很方便。然后类将扩展默认值。更新:本质上的事情是如我上面所描述的。至少有3个派生类扩展了
mysql
:com.mysql.jdbc.Driver驱动程序
com.mysql.fabric.jdbc.FabricMySQLDriver
com.mysql.jdbc.NonRegisteringReplicationDriver
虽然
com.mysql.jdbc.Driver
是默认实现,但其他方法重写基类中的某些方法。如果com.mysql.jdbc.NonRegisteringDriver
包含用于创建其实例并注册它的静态块,那么在内存中就不可能有一个所需的带有派生类的com.mysql.jdbc.Driver
驱动程序。但总的来说,这并没有强有力的理由。例如
NonRegisteringDriver
实现contains完全实现mysql
本身。