详解Mybatis中的PooledDataSource
作者:周杰伦本人 时间:2022-10-24 18:08:11
前言
上篇Java Mybatis数据源之工厂模式文章中我们介绍了Mybatis的数据源模块的DataSource接口和它对应的实现类UnpooledDataSource、PooledDataSource,这篇文章详细介绍一下PooledDataSource
PooledDataSource使用了数据库连接池可以实现数据库连接池的重复利用,还能控制连接数据库的连接上限,实现数据库连接的统一管理,缓存数据连接信息还能防止流量突发连接数据库不及时
PooledDataSource有个PoolState状态,PoolState里保存着数据库连接信息PooledConnection,PooledConnection实现InvocationHandler接口,重写invoke方法,显然这是一个代理类,使用了JDK的 *
PooledConnection
class PooledConnection implements InvocationHandler {
private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
public PooledConnection(Connection connection, PooledDataSource dataSource) {
this.hashCode = connection.hashCode();
this.realConnection = connection;
this.dataSource = dataSource;
this.createdTimestamp = System.currentTimeMillis();
this.lastUsedTimestamp = System.currentTimeMillis();
this.valid = true;
this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (CLOSE.equals(methodName)) {
dataSource.pushConnection(this);
return null;
}
try {
if (!Object.class.equals(method.getDeclaringClass())) {
checkConnection();
}
return method.invoke(realConnection, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
我们看一看到构造方法中调用了Proxy.newProxyInstance()方法来生成代理类,而重写invoke方法中如果是close()就调用pushConnection()方法直接把它放入连接池而不是关闭连接,其他情况调用checkConnection()检查连接信息,代理类调用realConnection()方法,下面就看一下pushConnection()方法
PooledDataSource的pushConnection()方法
方法的功能就是把数据库连接放入连接池中:
protected void pushConnection(PooledConnection conn) throws SQLException {
synchronized (state) {
state.activeConnections.remove(conn);
if (conn.isValid()) {
if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
state.idleConnections.add(newConn);
newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
}
state.notifyAll();
} else {
state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.getRealConnection().close();
if (log.isDebugEnabled()) {
log.debug("Closed connection " + conn.getRealHashCode() + ".");
}
conn.invalidate();
}
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
}
state.badConnectionCount++;
}
}
}
从活跃连接集合中删除该连接
如果PooledConnection有效,并且空闲连接数小于最大空闲连接数,就利用当前PooledConnection创建PooledConnection,放入空闲连接数集合中,方便下次使用,关闭当前PooledConnection对象的数据库连接,并对当前PooledConnection对象设置无效,最后唤醒其他等待的线程。如果空闲连接数大于最大空闲连接数了就关闭连接,设置当前连接无效
如果PooledConnection无效,badConnectionCount加一,这个badConnectionCount是记录无效的数据库连接信息的
来源:https://blog.51cto.com/u_15460453/5375552
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Struts2拦截器 关于解决登录的问题
![](https://img.aspxhome.com/file/2023/1/78241_0s.png)
Java读写文件创建文件夹多种方法示例详解
android的RecyclerView实现拖拽排序和侧滑删除示例
![](https://img.aspxhome.com/file/2023/4/100594_0s.gif)
Java设计模式之工厂模式案例详解
![](https://img.aspxhome.com/file/2023/2/60342_0s.png)
android侧滑菜单控件DrawerLayout使用方法详解
![](https://img.aspxhome.com/file/2023/5/139665_0s.png)
Maven打包jar生成javadoc文件和source文件代码实例
springboot整合通用Mapper简化单表操作详解
SpringBoot集成elasticsearch使用图文详解
![](https://img.aspxhome.com/file/2023/0/70490_0s.png)
Java中使用Lambda表达式和函数编程示例
android JSON解析数据 android解析天气预报
![](https://img.aspxhome.com/file/2023/6/94986_0s.jpg)
C#实现飞行棋源码
Mybatis在sqlite中无法读写byte[]类问题的解决办法
Spring中自定义数据类型转换的方法详解
图文详解SpringBoot中Log日志的集成
![](https://img.aspxhome.com/file/2023/5/62425_0s.png)
Android自定义View仿大众点评星星评分控件
![](https://img.aspxhome.com/file/2023/8/138358_0s.gif)
Java链表(Linked List)基本原理与实现方法入门示例
![](https://img.aspxhome.com/file/2023/4/60824_0s.png)
Android AlertDialog(对话框)实例详解
![](https://img.aspxhome.com/file/2023/6/126776_0s.jpg)
Android WebView实现长按保存图片及长按识别二维码功能
![](https://img.aspxhome.com/file/2023/6/139336_0s.gif)