在没有 Class.forName() 或系统属性的情况下如何加载 JDBC 驱动程序? [复制]
Posted
技术标签:
【中文标题】在没有 Class.forName() 或系统属性的情况下如何加载 JDBC 驱动程序? [复制]【英文标题】:How are JDBC drivers loaded without Class.forName() or System Properties? [duplicate] 【发布时间】:2019-01-10 04:10:52 【问题描述】:我正在尝试了解 JDBC 内部结构,具体来说,我的 JDBC 驱动程序是如何加载的,如果 1. 我没有使用 Class.forName() 2. 检查 jdbc.driver 系统属性返回 null。
我已尝试检查我的类路径并将系统属性的完整列表打印到控制台以按照https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html#registerDriver-java.sql.Driver- 和https://db.apache.org/derby/docs/10.4/devguide/cdevdvlp40653.html 进行检查
下面是 DBConnection 类的 DBConnection 构造函数
`public DBConnection()
try
this.conn = DriverManager.getConnection(JDBC_URL);
if (this.conn != null)
System.out.println("Connection successful");
catch(SQLException sqlex)
System.out.println("Connection failed");
`
下面是 main()
public static void main(String[] args)
DBConnection dbTest = new DBConnection();
String sysPropsString = System.getProperties().toString();
String[] propsArr = sysPropsString.split(",");
for(String property : propsArr)
if (property.contains("class") && property.contains("path")
&& (property.contains("derby") || property.contains("drivers")))
System.out.println(property);
System.out.println("***********************************");
String sysDrivers = System.getProperty("jdbc.drivers");
System.out.println(sysDrivers);
我希望通过 System.getProperty() 调用将 derby jdbc 驱动程序打印到控制台,或者在类路径中的某个位置找到它,但我没有看到。 derby 驱动是如何加载的?
下面是输出:
连接成功
java.class.path=/Users/aslotu/eclipse-workspace/Bullhorn/build/classes:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_cs.jar: /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_de_DE.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_es。 jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_fr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/ derbyLocale_hu.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_it.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/ lib/derbyLocale_ja_JP.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_ko_KR.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/ db/lib/derbyLocale_pl.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_pt_BR.jar:/Lib rary/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_ru.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_zh_CN.jar :/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derbyLocale_zh_TW.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derby .jar
空
【问题讨论】:
从 Java 6 (JDBC 4) 开始,您不需要Class.forName
来加载 JDBC 驱动程序。相反,如JDBC 4.0 and 4.1 features summary 中所述,自动加载 JDBC 驱动程序。 在早期版本的 JDBC 中,应用程序必须在请求连接之前手动注册驱动程序。使用 JDBC 4.0,应用程序不再需要在驱动程序名称上发出 Class.forName();相反,当应用程序请求连接时,DriverManager 会找到合适的 JDBC 驱动程序。
我不确定是否需要 Class.forName()
用于较新版本的 Java。但是对于您的问题:建议:尝试加载驱动程序,然后 ClassLoader.getSystemClassLoader();
,并打印出来自 URL[] urls = ((URLClassLoader)cl).getURLs()
的所有 URL
另见Technotes - JAR File Specification - Service Provider。
当您打印出java.class.path
时,它以“...:/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/db/lib/derby.jar”结尾。在我看来,这就像 Derby JDBC 驱动程序。您是否在问您的应用程序如何知道 使用该 .jar 文件?
在 Java 6 中是否需要 Class.forName
取决于驱动程序是否使用正确的类名声明 /META-INF/services/java.sql.Driver
,以及驱动程序 jar 是否位于初始类路径或不是。自动加载驱动程序不适用于上下文类路径上的驱动程序(一个常见的例子是放置在 WAR 的WEB-INF/lib
中的驱动程序;那些不会自动加载)。
【参考方案1】:
derby.jar
包含文件META-INF/services/java.sql.Driver
注册org.apache.derby.jdbc.AutoloadedDriver
。
这项工作是因为 DriverManager
使用 ServiceLoader
。
【讨论】:
这不是一个真正的答案,因为它高度特定于特定的驱动程序实现。 @jwenting 问题不是针对具体实现的吗? 不像我读的那样。他以德比为例,但在问题本身的文本中没有提到它。 @jwenting 我回答了问题是如何被问到的:“德比驱动程序是如何加载的?” @jwenting 它实际上对所有 JDBC 驱动程序都一样,唯一的区别是META-INF/services/java.sql.Driver
中的确切类名。以上是关于在没有 Class.forName() 或系统属性的情况下如何加载 JDBC 驱动程序? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
ClassLoader.loadClass和Class.forName的区别
ClassLoader.loadClass和Class.forName的区别