Druid连接池关键代码解读
Druid连接池中的一个方法,作用是获取一个数据库连接(DruidPooledConnection
)。下面对其中的主要逻辑进行解释:
getConnectionInternal(maxWaitMillis)
:调用内部方法获取数据库连接。如果连接池已满或获取连接超时,则会抛出异常GetConnectionTimeoutException
。isTestOnBorrow()
:检查是否需要在借用连接时进行连接有效性验证。- 如果需要验证连接有效性:
- 调用
testConnectionInternal(poolableConnection.getConnection())
方法测试连接的有效性。如果连接有效,则跳出循环。 - 如果连接无效,将其丢弃并从连接池中移除。
- 调用
- 如果需要验证连接有效性:
- 如果不需要在借用连接时进行连接有效性验证:
- 检查连接是否已关闭,如果是,则丢弃该连接。
- 如果开启了空闲连接验证(
isTestWhileIdle()
):- 计算连接的空闲时间。
- 如果空闲时间超过了设定的时间间隔(
timeBetweenEvictionRunsMillis
),则检查连接的有效性。 - 如果连接有效,则跳出循环。
- 如果连接无效,将其丢弃并从连接池中移除。
- 如果开启了移除废弃连接(
isRemoveAbandoned()
):- 获取当前线程的堆栈信息,并将其设置到连接对象中。
- 设置连接开始时间和追踪状态。
- 将连接加入活跃连接集合中。
- 如果未开启默认自动提交(
isDefaultAutoCommit()
):- 将连接的自动提交设置为false。
- 返回获取的连接对象。
总体来说,这段代码的作用是从Druid连接池中获取一个可用的数据库连接,并在一系列条件判断和验证后返回该连接对象。其中包括了连接超时处理、连接有效性验证、废弃连接移除等功能,保证连接的可用性和质量。
解读的代码如下:
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
DruidPooledConnection poolableConnection;
while(true) {
while(true) {
try {
poolableConnection = this.getConnectionInternal(maxWaitMillis);
break;
} catch (GetConnectionTimeoutException var17) {
if (notFullTimeoutRetryCnt > this.notFullTimeoutRetryCount || this.isFull()) {
throw var17;
}
++notFullTimeoutRetryCnt;
if (LOG.isWarnEnabled()) {
LOG.warn("not full timeout retry : " + notFullTimeoutRetryCnt);
}
}
}
if (this.isTestOnBorrow()) {
boolean validate = this.testConnectionInternal(poolableConnection.getConnection());
if (validate) {
break;
}
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
Connection realConnection = poolableConnection.getConnection();
this.discardConnection(realConnection);
} else {
Connection realConnection = poolableConnection.getConnection();
if (realConnection.isClosed()) {
this.discardConnection((Connection)null);
} else {
if (!this.isTestWhileIdle()) {
break;
}
long currentTimeMillis = System.currentTimeMillis();
long lastActiveTimeMillis = poolableConnection.getConnectionHolder().getLastActiveTimeMillis();
long idleMillis = currentTimeMillis - lastActiveTimeMillis;
long timeBetweenEvictionRunsMillis = this.getTimeBetweenEvictionRunsMillis();
if (timeBetweenEvictionRunsMillis <= 0L) {
timeBetweenEvictionRunsMillis = 60000L;
}
if (idleMillis < timeBetweenEvictionRunsMillis) {
break;
}
boolean validate = this.testConnectionInternal(poolableConnection.getConnection());
if (validate) {
break;
}
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
this.discardConnection(realConnection);
}
}
}
if (this.isRemoveAbandoned()) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.setConnectStackTrace(stackTrace);
poolableConnection.setConnectedTimeNano();
poolableConnection.setTraceEnable(true);
synchronized(this.activeConnections) {
this.activeConnections.put(poolableConnection, PRESENT);
}
}
if (!this.isDefaultAutoCommit()) {
poolableConnection.setAutoCommit(false);
}
return poolableConnection;
}