Java 为什么DriverManager.getConnection不使用Driver.class中的“acceptsURL”方法

Java 为什么DriverManager.getConnection不使用Driver.class中的“acceptsURL”方法,java,jdbc,Java,Jdbc,我正在阅读JDBC代码。在DriverManager.getConnection中,我发现它是这样工作的:它尝试连接它知道的每个驱动程序,直到成功 代码如下: for(DriverInfo aDriver : registeredDrivers) { // If the caller does not have permission to load the driver then // skip it. if

我正在阅读JDBC代码。在DriverManager.getConnection中,我发现它是这样工作的:它尝试连接它知道的每个驱动程序,直到成功

代码如下:

        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }

            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }

        }
但接口驱动程序中有一个方法acceptsURL:

    boolean acceptsURL(String url) throws SQLException;
所以我的问题是,为什么DriverManager在进行真正的连接以过滤不相关的驱动程序之前不调用此方法

或者使用代码,这可能更好吗

        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL) && aDriver.driver.acceptsURL(url)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }

            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }

        }
DriverManager引用实现OpenJDK不使用acceptsUrl。这并不一定意味着没有使用它的DriverManager实现。事实上,据我回忆,早期的Sun Java实现确实调用了acceptsURL。未调用它的主要原因是JDBC规范要求DriverManager无论如何都要对每个已注册的驱动程序调用connect。见下文

规范或API文档中没有说明DriverManager必须使用acceptsURL。本节仅说明第9.2节驱动程序界面:

DriverManager类在需要时调用驱动程序方法 与注册的驱动程序交互。驱动程序接口也可以 包括方法acceptsURL。DriverManager可以使用此选项 方法来确定应使用哪些已注册的驱动程序 给定的URL

重点矿山

注意使用can这个词代替must或will

下一段说:

当DriverManager试图建立连接时,它调用 该驱动程序的connect方法,并向驱动程序传递URL。如果 驱动程序实现理解URL,它将返回 连接对象,或者在连接无法启动时引发SQLException 将[原文如此]输入数据库。如果驱动程序实现 不理解URL,它将返回null

此外,DriverManager类的第9.4节说明:

getConnection—JDBC客户端调用以建立连接的方法。调用包括一个JDBC URL,该URL DriverManager传递给其列表中的每个驱动程序,直到找到为止 其Driver.connect方法识别URL的人。该驱动程序向DriverManager返回一个连接对象,DriverManager反过来 将其传递给应用程序。 重点矿山

在我看来,无论如何都需要在每个驱动程序上调用Driver.connect,所以实现调用acceptsURL没有意义

现在,至于JDBC规范为什么是这样写的,我不知道,我自己也是JSR-221JDBC4专家组的成员。当我加入专家组时,实现和规范已经是这样了,所以我不知道它的历史。然而,我不确定你会在这里得到一个比上述不满意答案更好的答案,因为规范上是这么说的

然而,如果我不得不猜测的话,这可能是因为对于一些司机来说,决定他们是否可以接受URL可能相对复杂或昂贵。在这种情况下,最好只是尝试并连接,因为对于拒绝URL的驱动程序,成本等于或应该等于只调用acceptsURL,而对于实际接受URL的驱动程序,如果DriverManager先调用acceptsURL,然后再调用connect,则成本将受到两次影响

这并不意味着acceptsURL方法完全没有价值。一些应用程序(例如一些查询工具或报告工具)使用它来发现哪些驱动程序将处理特定的URL,因此它们可以查询驱动程序实现中支持的连接属性,以便使用可用属性填充连接向导。其他程序可以使用它来获取诸如版本、父记录器或JDBC兼容性等信息。

DriverManager参考实现OpenJDK不使用acceptsUrl。这并不一定意味着没有使用它的DriverManager实现。事实上,据我回忆,早期的Sun Java实现确实调用了acceptsURL。未调用它的主要原因是JDBC规范要求DriverManager无论如何都要对每个已注册的驱动程序调用connect。见下文

规范或API文档中没有说明DriverManager必须使用acceptsURL。本节中的驱动程序仅说明:

DriverManager类在需要时调用驱动程序方法 与注册的驱动程序交互。驱动程序接口也可以 包括方法acceptsURL。DriverManager可以使用此选项 方法来确定应使用哪些已注册的驱动程序 给定的URL

重点矿山

注意使用can这个词代替must或will

下一段说:

当DriverManager试图建立连接时,它调用 该驱动程序的connect方法,并向驱动程序传递URL。如果 驱动程序实现理解URL,它将返回 连接对象,或在以下情况下引发SQLException 无法建立连接 将[原文如此]输入数据库。如果驱动程序实现 不理解URL,它将返回null

此外,DriverManager类的第9.4节说明:

getConnection—JDBC客户端调用以建立连接的方法。调用包括一个JDBC URL,该URL DriverManager传递给其列表中的每个驱动程序,直到找到为止 其Driver.connect方法识别URL的人。该驱动程序向DriverManager返回一个连接对象,DriverManager反过来 将其传递给应用程序。 重点矿山

在我看来,无论如何都需要在每个驱动程序上调用Driver.connect,所以实现调用acceptsURL没有意义

现在,至于JDBC规范为什么是这样写的,我不知道,我自己也是JSR-221JDBC4专家组的成员。当我加入专家组时,实现和规范已经是这样了,所以我不知道它的历史。然而,我不确定你会在这里得到一个比上述不满意答案更好的答案,因为规范上是这么说的

然而,如果我不得不猜测的话,这可能是因为对于一些司机来说,决定他们是否可以接受URL可能相对复杂或昂贵。在这种情况下,最好只是尝试并连接,因为对于拒绝URL的驱动程序,成本等于或应该等于只调用acceptsURL,而对于实际接受URL的驱动程序,如果DriverManager先调用acceptsURL,然后再调用connect,则成本将受到两次影响

这并不意味着acceptsURL方法完全没有价值。一些应用程序(例如一些查询工具或报告工具)使用它来发现哪些驱动程序将处理特定的URL,因此它们可以查询驱动程序实现中支持的连接属性,以便使用可用属性填充连接向导。其他程序可以使用它来获取诸如版本、父记录器或JDBC兼容性等信息