1.核心定位:JDBC 生态的 “驱动调度中枢”,用于管理数据库驱动实例。DriverManager 是 JDBC 核心工具类(java.sql.DriverManager)
2.是只能管理数据库的驱动实例吗?其他的驱动不能管吗?
- 明确结论:DriverManager 只管理 “符合 JDBC 规范的数据库驱动实例”(即实现了 java.sql.Driver 接口的实例,如 MySQL 的
com.mysql.cj.jdbc.Driver、 Oracle的oracle.jdbc.driver.OracleDriver),不管理其他任何 “非 JDBC 驱动实例”。 - DriverManager 的设计目标是 “为 JDBC 数据库连接提供统一的驱动管理”,其管理范围有严格边界。
从底层源码来认识DriverManager
1.核心存储:驱动元信息集合(registeredDrivers)
// 存储驱动元信息的核心集合,线程安全的写时复制容器
private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
存储元素:不是直接存储 Driver 实例,而是 DriverInfo(DriverManager 内部静态私有类),封装了 Driver 实例、类加载器、注销状态、权限等元信息; DriverInfo具体代码如下:
// DriverManager 内部静态私有类
private static class DriverInfo {// 核心:封装的 JDBC 驱动实例(实现了 java.sql.Driver 接口)final Driver driver;// 加载该驱动的类加载器(关键:用于类加载器适配和可见性判断)final ClassLoader classLoader;// 驱动的注销状态标记(默认 false:未注销;true:已注销)volatile boolean deregistered;// 驱动的权限对象(用于安全管理器的权限校验)private final SQLPermission permission;// 构造方法:创建 DriverInfo 时必须传入 Driver 实例和类加载器DriverInfo(Driver driver, ClassLoader classLoader) {this.driver = driver;this.classLoader = classLoader;this.deregistered = false;// 创建权限对象(用于后续 deregisterDriver 等操作的权限校验)this.permission = new SQLPermission("deregisterDriver");}
}
2.向 DriverManager 中注册驱动,即将 DriverInfo 加入集合
// 驱动注册方法:registerDriver 是外部触发入口(驱动静态代码块自动调用)
public static void registerDriver(Driver driver) throws SQLException {if (driver == null) {throw new NullPointerException("驱动实例不能为 null");}// 1. 获取当前线程的类加载器(用于封装到 DriverInfo)ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// 2. 创建 DriverInfo 实例(封装驱动+类加载器等元信息)DriverInfo driverInfo = new DriverInfo(driver, classLoader);// 3. 核心操作:将 DriverInfo 加入 registeredDrivers 集合registeredDrivers.add(driverInfo);// 可选:打印调试日志(若开启日志)println("已注册驱动元信息:" + driverInfo.driver.getClass().getName());
}
3.获取连接核心源码 getConnection(String url, Properties info),遍历驱动器,找到能处理当前链接的驱动器,然后返回由由驱动创建的 Connection 对象,供上层使用。
private static Connection getConnection(String url, Properties info) throws SQLException {if (url == null || url.isEmpty()) {throw new SQLException("URL cannot be null or empty");}// 遍历所有已注册的驱动for (DriverInfo di : registeredDrivers) {if (di.deregistered) continue; // 跳过已注销的驱动try {// 筛选支持当前 URL 的驱动if (di.driver.acceptsURL(url)) {println("Trying to connect with driver: " + di.driver.getClass().getName());// 调用驱动的 connect 方法获取连接Connection conn = di.driver.connect(url, info);if (conn != null) {println("Connection successful");return conn;}}} catch (SQLException e) {println("Driver " + di.driver.getClass().getName() + " failed: " + e.getMessage());// 不中断,继续尝试下一个驱动}}// 所有驱动都失败,抛出异常throw new SQLException("No suitable driver found for " + url);
}
下一节重点讲解 Connection 对象