主要看DruidDataSource这个类
看怎么创建连接的要从getConnection()这个方法看起
getConnection()中有个init()初始化方法
init做的事情就是加锁,然后判断各种条件参数是否符合要求,给内部各种参数赋值
需要关心的就是下面的代码
connections = new DruidConnectionHolder[maxActive];
evictConnections = new DruidConnectionHolder[maxActive];
keepAliveConnections = new DruidConnectionHolder[maxActive];
这三个数组里面放了具体的连接
一个存放所有连接,一个回收的连接,一个放存活在保持的连接
需要注意的是这三个数组里面放的是DruidConnectionHolder对象,这个对应是对PhysicalConnectionInfo物理连接信息进行包装的一个类,而PhysicalConnectionInfo又是对Connection的一次包装
下面这段代码就是具体的初始化连接池的过程
主要分为同步和异步
异步就是将创建连接的任务交给一个线程池去处理,一直异步创建知道达到initialSize为止
同步的过程大致差不多
if (createScheduler != null && asyncInit) {
for (int i = 0; i < initialSize; ++i) {
createTaskCount++;
CreateConnectionTask task = new CreateConnectionTask(true);
this.createSchedulerFuture = createScheduler.submit(task);
}
} else if (!asyncInit) {
// init connections
while (poolingCount < initialSize) {
try {
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
connections[poolingCount++] = holder;
} catch (SQLException ex) {
LOG.error("init datasource error, url: " + this.getUrl(), ex);
if (initExceptionThrow) {
connectError = ex;
break;
} else {
Thread.sleep(3000);
}
}
}
if (poolingCount > 0) {
poolingPeak = poolingCount;
poolingPeakTime = System.currentTimeMillis();
}
}
里面有个内部类CreateConnectionTask,这个类是一个实现了runnable接口的任务类,用于创建连接
下面看具体方法runInternal
PhysicalConnectionInfo physicalConnection = null;
try {
physicalConnection = createPhysicalConnection();
} catch (OutOfMemoryError e) {
}
createPhysicalConnection方法之前有一些加锁判断条件之类的代码,我们这里忽略,只关心创建的方法
createPhysicalConnection这个方法在抽象父类DruidAbstractDataSource中
做的事情就是根据各种配置中读取的参数来创建一个物理连接
创建好了之后通过调用put方法,将physicalConnection封装成DruidConnectionHolder然后放入到connections数组中
boolean result = put(physicalConnection);
protected boolean put(PhysicalConnectionInfo physicalConnectionInfo) {
DruidConnectionHolder holder = null;
try {
holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo);
} catch (SQLException ex) {
lock.lock();
try {
if (createScheduler != null) {
createTaskCount--;
}
} finally {
lock.unlock();
}
LOG.error("create connection holder error", ex);
return false;
}
return put(holder);
}
private boolean put(DruidConnectionHolder holder) {
lock.lock();
try {
if (poolingCount >= maxActive) {
return false;
}
connections[poolingCount] = holder;
incrementPoolingCount();
if (poolingCount > poolingPeak) {
poolingPeak = poolingCount;
poolingPeakTime = System.currentTimeMillis();
}
notEmpty.signal();
notEmptySignalCount++;
if (createScheduler != null) {
createTaskCount--;
if (poolingCount + createTaskCount < notEmptyWaitThreadCount //
&& activeCount + poolingCount + createTaskCount < maxActive) {
emptySignal();
}
}
} finally {
lock.unlock();
}
return true;
}
我们还是从getConnection()方法看起
getConnection()调用了getConnection(long maxWaitMillis) 其中已经init()过了,所以这次inti()方法直接return了
我们主要看getConnectionDirect(maxWaitMillis)这个方法
@Override
public DruidPooledConnection getConnection() throws SQLException {
return getConnection(maxWait);
}
public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
init();
if (filters.size() > 0) {
FilterChainImpl filterChain = new FilterChainImpl(this);
return filterChain.dataSource_connect(this, maxWaitMillis);
} else {
return getConnectionDirect(maxWaitMillis);
}
}
getConnectionDirect(maxWaitMillis)这个方法很长,主要是一些状态更新很判断过程,我们重点看下面的部分
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
//...
DruidPooledConnection poolableConnection;
try {
poolableConnection = getConnectionInternal(maxWaitMillis);
} catch (GetConnectionTimeoutException ex) {
//...
}
//...
getConnectionInternal这个方法会从数组中获取holder对象,然后封装成connection返回
重点看如下部分pollLast(nanos)和takeLast()都会从connections数组尾端中拿到holder对象
然后封装成DruidPooledConnection对象返回
private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
DruidConnectionHolder holder;
//...
if (maxWait > 0) {
holder = pollLast(nanos);
} else {
holder = takeLast();
}
//...
DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);
return poolalbeConnection;
}
大致过程如此,实际情况复杂很多,涉及到很多加锁通知,内部状态更新很多其他操作,有兴趣的朋友可以看看源码
本文中的源码是基于1.1.16版本