在阅读DBCP源码前得先阅读commons-pool的原源码。
下面是几个主要的类的关系图。
1、BasicDataSource是我们最常见的类,配置数据源的时候就是写的这个。
它里面有一个getConnection方法,每次调用时就是从连接池中获取Connection。
具体的实现方法是在PoolingDataSource.java中,源码中如下:
public Connection getConnection() throws SQLException {
try {
Connection conn = (Connection)(_pool.borrowObject());
if (conn != null) {
conn = new PoolGuardConnectionWrapper(conn);
}
return conn;
} catch(SQLException e) {
throw e;
} catch(NoSuchElementException e) {
throw new SQLNestedException("Cannot get a connection, pool error " + e.getMessage(), e);
} catch(RuntimeException e) {
throw e;
} catch(Exception e) {
throw new SQLNestedException("Cannot get a connection, general error", e);
}
}
里面的_pool.borrowObject();就是从池中获取对象。
2、接着看PoolableConnectionFactory.java 这个就是commons-pool需要我们实现的创建池化对象的工厂类。
public Object makeObject() throws Exception {
Connection conn = _connFactory.createConnection();
if (conn == null) {
throw new IllegalStateException("Connection factory returned null from createConnection");
}
initializeConnection(conn);
if(null != _stmtPoolFactory) {
KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
conn = new PoolingConnection(conn,stmtpool);
stmtpool.setFactory((PoolingConnection)conn);
}
return new PoolableConnection(conn,_pool,_config);
}
这段代码就是调用ConnectionFactory创建连接对象的方法,并且返回的是封装好的PoolableConnection类。
3、最后看PoolingConnection.java 中的close方法。
public synchronized void close() throws SQLException {
if (_closed) {
return;
}
boolean isUnderlyingConectionClosed;
try {
isUnderlyingConectionClosed = _conn.isClosed();
} catch (SQLException e) {
try {
_pool.invalidateObject(this);
} catch(IllegalStateException ise) {
passivate();
getInnermostDelegate().close();
} catch (Exception ie) {
}
throw (SQLException) new SQLException("Cannot close connection (isClosed check failed)").initCause(e);
}
if (!isUnderlyingConectionClosed) {
try {
_pool.returnObject(this);
} catch(IllegalStateException e) {
passivate();
getInnermostDelegate().close();
} catch(SQLException e) {
throw e;
} catch(RuntimeException e) {
throw e;
} catch(Exception e) {
throw (SQLException) new SQLException("Cannot close connection (return to pool failed)").initCause(e);
}
} else {
try {
_pool.invalidateObject(this); // XXX should be guarded to happen at most once
} catch(IllegalStateException e) {
// pool is closed, so close the connection
passivate();
getInnermostDelegate().close();
} catch (Exception ie) {
}
throw new SQLException("Already closed.");
}
}
最后这个close方法里面是把对象给return到pool中。
看到这里,在使用DBCP时还是得调用close方法一下,把连接还给pool。