问题描述
Java6, 也就是 JDBC4.0 之后 JavaSE 项目可以自动加载注册驱动是因为数据库厂商提供了下面这个文件
位置:
META-INF -> services -> java.sql.Driver
内容
com.mysql.jdbc.Driver
经过查看源码发现
java.sql.DriverManager.getConnection(String url, String user, String password) {
return (getConnection(url, info, Reflection.getCallerClass()));
}
|
|
V
java.sql.DriverManager.getConnection(String url, Properties info, Class<?> caller) {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
}
好像也没有用到这个文件,感觉好像是caller.getClassLoader()
就加载了注册驱动, 好像是都可以直接加载,为什么还要手动加载
还有JavaEE为什么还要手动加载
问题解决
java.sql.DriverManager 类中说到
The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry:
my.sql.Driver
那么, 什么是 Java Standard Edition Service Provider mechanism
接着,
When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from amongst those loaded at initialization and those loaded explicitly using the same classloader as the current applet or application.
也就是说, 当 getConnection 被调用的时候, DriverManager 会尝试使用当前程序的类加载器中定位一个 driver.