public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
// 初始化,即主流程2
init();
if (filters.size() > 0) {
// 责任链,内部也是触发下面的 getConnectionDirect 方法,只是要走一遍责任链上每个 filter 的逻辑,这里不做描述,后续放到流程 1.1 里体现
FilterChainImpl filterChain = new FilterChainImpl(this);
return filterChain.dataSource_connect(this, maxWaitMillis);
} else {
// 触发 getConnectionDirect
return getConnectionDirect(maxWaitMillis);
}
}
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
// 死循环
for (;;) {
/**
* 真正返回出去的连接对象,注意这里是被 druid 包装成了 DruidPooledConnection 类型,
* 实际上池子里存放的连接类型是 DruidConnectionHolder,DruidPooledConnection 类本身持有一个 holder 属性,
* 用于保存真正的连接对象,而 DruidConnectionHolder 才是真正保存驱动连接对象的类。
*/
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try {
// 从池子里获取连接,这一个后续放到流程 1.2 体现
poolableConnection = getConnectionInternal(maxWaitMillis);
} catch (GetConnectionTimeoutException ex) {
// 出现了超时异常,在连接池没满且重试次数未超过上限的情况下,重试一次( notFullTimeoutRetryCount 默认是 0,所以至少可以重试一次)。
if (notFullTimeoutRetryCnt <= this.notFullTimeoutRetryCount && !isFull()) {
// 重试次数+1
notFullTimeoutRetryCnt++;
if (LOG.isWarnEnabled()) {
LOG.warn("get connection timeout retry : " + notFullTimeoutRetryCnt);
}
continue;
}
// 超过重试次数或者池子已满仍然获取失败,则直接抛出异常
throw ex;
}
// testOnBorrow 开启时,每次都进行检测连接可用性
if (testOnBorrow) {
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
// 若连接不可用,则触发 discard,这个方法具体放到流程 1.4 体现
discardConnection(poolableConnection.holder);
continue;
}
} else {
if (poolableConnection.conn.isClosed()) {
// 传入null,避免重复关闭
discardConnection(poolableConnection.holder);
continue;
}
// 不启用 testOnBorrow 的情况下,才会判断是否启用 testWhileIdle
if (testWhileIdle) {
final DruidConnectionHolder holder = poolableConnection.holder;
long currentTimeMillis = System.currentTimeMillis();
long lastActiveTimeMillis = holder.lastActiveTimeMillis;
// 上次被使用的时间
long lastExecTimeMillis = holder.lastExecTimeMillis;
// keepAlive 启用情况下,上次存活检测的时间,和 keepAliveBetweenTimeMillis 相关
long lastKeepTimeMillis = holder.lastKeepTimeMillis;
if (checkExecuteTime
&& lastExecTimeMillis != lastActiveTimeMillis) {
lastActiveTimeMillis = lastExecTimeMillis;
}
// 若在 timeBetweenEvictionRunsMillis 时间内,已经被 keepAliveBetweenTimeMillis 所检测,则不再次检测,避免重复检测耗费性能
if (lastKeepTimeMillis > lastActiveTimeMillis) {
lastActiveTimeMillis = lastKeepTimeMillis;
}
// 计算出闲置时间
long idleMillis = currentTimeMillis - lastActiveTimeMillis;
long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis <= 0) {
timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
}
// 当闲置时间超出 timeBetweenEvictionRunsMillis(默认60s)时,则触发检查逻辑
if (idleMillis >= timeBetweenEvictionRunsMillis
|| idleMillis < 0 // unexcepted branch
) {
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
//连接不可用,同样触发 discard
discardConnection(poolableConnection.holder);
continue;
}
}
}
}
// 若开启 removeAbandoned,则把当前拿到的连接放到 activeConnections 里,方便后续检查(后面流程 4.2 体现)
if (removeAbandoned) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
poolableConnection.connectStackTrace = stackTrace;
// 设置连接获取时间为当前时间
poolableConnection.setConnectedTimeNano();
// 这个设置为 true,则在归还该连接时会在 activeConnections 里清除掉该连接对象
poolableConnection.traceEnable = true;
activeConnectionLock.lock();
try {
activeConnections.put(poolableConnection, PRESENT);
} finally {
activeConnectionLock.unlock();
}
}
// 默认是不开事务的,所以这里是 true,不会触发下面的逻辑;这个不建议手动设置默认值,一般开启事务的工作自己做或者交给第三方框架(如 spring)做比较好
if (!this.defaultAutoCommit) {
poolableConnection.setAutoCommit(false);
}
// 最终返回可用连接
return poolableConnection;
}
}