dbcp源码解析
PoolingDataSource类
public Connection getConnection()
throws SQLException
{
Connection conn;
conn = (Connection)_pool.borrowObject();//从线程池取连接
if(conn != null)
conn = new PoolGuardConnectionWrapper(conn);
return conn;
............................................
}
AbandonedObjectPool类
public Object borrowObject() throws Exception {
if (config != null && config.getRemoveAbandoned() && getNumIdle() < 2
&& getNumActive() > getMaxActive() - 3)//回收连接事件发生的条件
removeAbandoned();
Object obj = super.borrowObject();
.....................
}
private void removeAbandoned() {
long now = System.currentTimeMillis();
long timeout = now - (long) (config.getRemoveAbandonedTimeout() * 1000);
ArrayList remove = new ArrayList();
synchronized (trace) {
Iterator it = trace.iterator();
do {
if (!it.hasNext())
break;
AbandonedTrace pc = (AbandonedTrace) it.next();
if (pc.getLastUsed() <= timeout && pc.getLastUsed() > 0L)//lastUsed是关键
remove.add(pc);
} while (true);
}
for (Iterator it = remove.iterator(); it.hasNext();) {
AbandonedTrace pc = (AbandonedTrace) it.next();
if (config.getLogAbandoned())
pc.printStackTrace();
try {
invalidateObject(pc);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 下面看lastUsed如何变化
GenericObjectPool类 (AbandonedObjectPool的父类)
public Object borrowObject()
throws Exception
{
........................
_factory.activateObject(latch.getPair().value);//激活连接
if(_testOnBorrow && !_factory.validateObject(latch.getPair().value))
throw new Exception("ValidateObject failed");
synchronized(this)
{
_numInternalProcessing--;
_numActive++;
}
..............
}
PoolableConnectionFactory 类
public void activateObject(Object obj) throws Exception {
if (obj instanceof DelegatingConnection)
((DelegatingConnection) obj).activate();
.......................
}
DelegatingConnection类(DelegatingConnection extends AbandonedTrace implements Connection)
protected void activate() {
_closed = false;
setLastUsed();//lastUsed赋值(当前系统时间)父类AbandonedTrace 中的方法
............................................
}
public void close() throws SQLException {//关闭连接时
passivate();
_conn.close();
}
protected void passivate()
throws SQLException
{
List statements = getTrace();
if(statements != null)
{
Statement set[] = new Statement[statements.size()];
statements.toArray(set);
for(int i = 0; i < set.length; i++)
set[i].close();
clearTrace();
}
setLastUsed(0L);//lastUsed置为0,置为闲置连接
...............
}
分析总结:removeAbandonedTimeout的含义是,在config != null(有配置) && config.getRemoveAbandoned() (removeAbandoned开启)&& getNumIdle()(闲置连接数) < 2
&& getNumActive() (活动连接数)> getMaxActive() - 3)时发起回收事件,
回满足pc.getLastUsed() <= timeout && pc.getLastUsed() > 0L(一直在活动状态,已经超时了)这样条件
的连接,连接从池中取出时lastUsed赋值为当前系统时间,关闭时,lastUsed置为0
补充:
PoolableConnection类(public class PoolableConnection extends DelegatingConnection)
从连接池中取出的连接应该是PoolableConnection的实例
public synchronized void close() throws SQLException {
boolean isClosed = false;
try {
isClosed = isClosed();
} catch (SQLException e) {
try {
_pool.invalidateObject(this);
} catch (Exception ie) {
}
throw new SQLNestedException(
"Cannot close connection (isClosed check failed)", e);
}
if (isClosed) {
try {
_pool.invalidateObject(this);
} catch (Exception ie) {
}
throw new SQLException("Already closed.");
}
try {
_pool.returnObject(this);
} catch (SQLException e) {
throw e;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new SQLNestedException(
"Cannot close connection (return to pool failed)", e);
}
}
当 removeAbandonedTimeout设的过小,而应用中又有某条sql执行时间过长,就会报Already closed.
此文章由 http://www.ositren.com 收集整理 ,地址为:
http://www.ositren.com/htmls/68245.html