数据库连接池通过动态代理封装真实Connection,其close()方法被重写为归还连接而非关闭物理连接;代理在getConnection()时创建,委托所有方法调用并增强监控、缓存等功能;真实连接与代理生命周期分离,实现高效复用。

数据库连接池底层通过动态代理(如 JDK Proxy 或 CGLIB)对真实 Connection 对象进行包装,使其在 close() 调用时不会真正关闭物理连接,而是归还到池中复用。
Connection 代理对象的创建时机
当应用调用 DataSource.getConnection() 时,连接池(如 HikariCP、Druid、DBCP)并不直接返回底层驱动创建的 Connection 实例,而是:
- 从池中取出一个空闲的真实 Connection(或新建一个)
- 用自定义的代理类(例如 HikariProxyConnection、DruidPooledConnection)对其进行封装
- 该代理类实现了 java.sql.Connection 接口,并持有一个对真实 Connection 的引用
- 所有接口方法(如 executeQuery、setAutoCommit)均委托给真实 Connection 执行
close() 方法被重写为“归还”而非“销毁”
这是复用的核心机制。代理 Connection 的 close() 方法不调用底层 driver 的 close(),而是:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 清空当前连接上的事务状态、临时表、会话变量等(如 resetConnection())
- 将自身标记为“空闲”,放回连接池的可用队列(如 ConcurrentLinkedQueue 或 FastList)
- 可能触发连接有效性检测(如 testOnReturn)
- HikariCP 中甚至会复用代理对象本身(避免频繁创建/销毁代理实例)
代理层如何拦截和增强行为
除了 close(),代理还会在关键方法上插入逻辑,实现监控、安全、诊断等功能:
立即学习“Java免费学习笔记(深入)”;
- setAutoCommit(boolean):记录调用栈,便于定位未提交事务
- prepareStatement(String):缓存 PreparedStatement 代理,支持语句池(如 Druid 的 statement-cache)
- isClosed():不仅检查真实连接是否关闭,还检查代理是否已被归还(防止二次 close)
- getMetaData():可能返回池级元数据(如连接获取时间、持有线程),用于排查慢 SQL 持有连接问题
真实连接与代理的生命周期分离
连接池管理两套生命周期:
- 物理连接(Real Connection):由 JDBC Driver 创建,受 maxLifetime、idleTimeout 控制,超时后被真实关闭
- 代理连接(PooledConnection / ProxyConnection):轻量对象,可被反复分配给不同业务线程;其 close() 只是逻辑归还
- 线程调用 getConnection() 得到的是代理,业务结束后 close(),池内部完成复位(如 rollback、clearWarnings)再放回

















