MyBatis 使用 javax.sql.DataSource 标准接口,通过工厂模式创建不同类型的数据源实现。使用对象池模式实现PooledDataSource,用代理模式改变Connection#close方法逻辑,实现资源归还。
理解MyBatis中连接池的实现,可为学习其他组件如Druid 、HikariCP打好基础。
注:本文中源码来自mybatis 3.4.x版本,地址github.com/mybatis/myb...
一 DataSourceFactory接口
工厂模式,声明创建DataSource实例方法,有3个实现:
- UnpooledDataSourceFactory,用于创建UnpooledDataSource
- PooledDataSourceFactory,继承自UnpooledDataSourceFactory,用于创建PooledDataSource
- JndiDataSourceFactory,第三方 DataSource (通过 JNDI 获取)
二 3种连接池
2.1 UnpooledDataSource
非池化数据源,有以下特点:
- 每次 getConnection() 都创建新的数据库连接
- 通过 DriverManager 获取连接
- 适用于简单应用或测试环境
核心属性如下。每次获取连接,都直接调用DriverManager.getConnection创建一个实例。 
2.2 PooledDataSource
池化数据源,维护一个池子(其实就是List),复用数据库连接,基于 UnpooledDataSource 实现。
PooledDataSource内部持有 UnpooledDataSource 创建真实连接,维护 PoolState 管理连接状态,使用动态代理拦截Connection.close() 方法,将连接归还到池子而非真的关闭。
连接池配置如下
连接池状态主要参数如下,使用中连接、空闲连接分别放在不同的List。
从PooledDataSource中获取到的连接,其实是一个代理对象。 
PooledConnection
PooledDataSource池中其实是PooledConnection对象(并没有实现Connection接口),它持有Connection实例、Connection代理对象,并且实现了InvocationHandler接口,声明了动态代理逻辑:
- 代理连接调用close方法时,会将连接放回连接池;
- 代理连接调用其他非Object的方法时,会先检查连接是否有效;
- 记录连接创建时间、最后一次使用时间、借出时间,用于连接有效性管理;

获取/归还连接

2.3 JndiDataSourceFactory
从 JNDI 上下文获取已配置的 DataSource,适用于应用服务器环境(如 Tomcat、WebLogic),不直接创建连接,而是使用容器管理的数据源。
三 池化模式实现
3.1 Mybatis的启发
MyBatis 的 PooledDataSource 虽然简单,但包含了池化技术的核心思想,比如:
- 对象复用而非对象共享
池化不是简单地复用对象本身,而是复用昂贵的底层资源(真实连接),通过新包装对象隔离使用状态。
java
// 归还时创建新的包装对象
PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
state.idleConnections.add(newConn);
conn.invalidate(); // 旧对象失效
- 动态代理拦截资源释放
通过代理模式透明地改变资源释放行为,用户无感知地实现池化。
java
// PooledConnection 实现 InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) {
if (CLOSE.equals(methodName)) {
// 归还而非关闭
dataSource.pushConnection(this);
return null;
}
return method.invoke(realConnection, args);
}
- 超时强制回收机制
防止资源泄漏的最后防线,避免因使用方忘记释放导致池耗尽。
java
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// 强制回收超时连接
state.activeConnections.remove(oldestActiveConnection);
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
}
- 状态与健康管理
除了检查资源状态,还需检查池中的connection是否断连。
java
protected boolean pingConnection(PooledConnection conn) {
// 1. 检查连接是否关闭
// 2. 可选:执行 ping 查询测试
// 3. 长时间未使用才 ping,避免频繁测试
}
- 监控与可观测性
设计详细的统计信息,便于分析性能、调优和问题诊断。
java
protected long requestCount; // 请求总数
protected long accumulatedRequestTime; // 累计请求时间
protected long accumulatedCheckoutTime; // 累计借出时间
protected long badConnectionCount; // 坏连接数
protected long hadToWaitCount; // 等待次数
3.2 通用池化实现
基于以上分析,可以抽象出通用的池化实现模式:
java
public class GenericObjectPool<T> {
// 1. 双列表管理
private List<PooledObject<T>> idle = new ArrayList<>();
private List<PooledObject<T>> active = new ArrayList<>();
// 2. 配置参数
private int maxTotal;
private int maxIdle;
private long maxWaitMillis;
// 3. 获取资源
public T borrow() {
synchronized (lock) {
// 优先从空闲列表获取
// 其次创建新对象
// 或回收超时对象
// 最后等待
lock.wait(maxWaitMillis);
}
}
// 4. 归还资源
public void return(T obj) {
synchronized (lock) {
// 验证有效性
// 重置状态
// 放回空闲列表或销毁
lock.notifyAll();
}
}
// 5. 健康检查
private boolean validate(T obj) {
}
// 6. 统计监控
private PoolStats stats;
}
