PooledDataSource类
PooledDataSource主要涉及到两个类PooledConnection以及PoolState
PooledConnection:PooledDataSource中创建的数据库连接,可以获得实际的realConnection和proxyConnection链接对象,重点说明PooledConnection实现了InvocationHandler(即实现Aop时⽤到的
⼀种动态代理)接⼝
PoolState:与PooledDataSource对应,记录数据源对应连接池的状态,包括空闲、活动链接数量,以及连接池的统计信息。
PooledConnection下的属性说明;
Connection realConnection:真正的⽤于连接数据库的连接,即各个JDBC封装后的Connection,例如org.hsqldb.jdbc.JDBCConnection实现的JDBC
Connection proxyConnection:通过动态代理获得的连接,
this.proxyConnection = (Connection) wProxyInstance(ClassLoader(), IFACES, this);
下⾯主要介绍PooledDataSource类中的⽅法:
1、构造⽅法:使⽤UnpooledDataSource⽅法返回UnpooledDataSource对象,同时⽣成数据源的hashcode(由url+urname+password的hashcode)
public PooledDataSource(String driver, String url, String urname, String password) {
dataSource = new UnpooledDataSource(driver, url, urname, password);
expectedConnectionTypeCode = Url(), Urname(), Password());
}
2、从连接池中获得链接,getConnection()是个中间⽅法,实际调⽤的是popConnection⽅法,下⾯介绍popConnection即从链接池中拿Connection。
@Override
public Connection getConnection() throws SQLException {
return Urname(), Password()).getProxyConnection();
}
private PooledConnection popConnection(String urname, String password) throws SQLException {
boolean countedWait = fal;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
//while + synchronized (state) ⽤于以同步⽅式拿出connection
while (conn == null) {
synchronized (state) {
//如果PoolState中的空闲连接数不为空,则直接拿出第⼀个链接
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
conn = ve(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + RealHashCode() + " from pool.");
}
} el {
// Pool does not have available connection
//如果PoolState中的空闲连接数为空,但是活动的链接数⼩于PooledDataSource设置的最⼤链接数,则可以新建链接
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
conn = new Connection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + RealHashCode() + ".");
}
} el {
// Cannot create new connection
//如果PoolState中的空闲连接数为空,并且活动的链接数不⼩于PooledDataSource设置的最⼤链接数,则先获得活动链接中最先使⽤链接(即最⽼的),判断是否超时时间,如果超时了,则重新从活动连接池中去掉该连接,然后在 PooledConnection oldestActiveConnection = (0);
long longestCheckoutTime = CheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
state.claimedOverdueConnectionCount++;
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
state.accumulatedCheckoutTime += longestCheckoutTime;
ve(oldestActiveConnection);
if (!RealConnection().getAutoCommit()) {
}
conn = new RealConnection(), this);
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + RealHashCode() + ".");
}
} el {
// Must wait
//如果PoolState中的空闲连接数为空,并且活动的链接数不⼩于PooledDataSource设置的最⼤链接数,则先获得活动链接中最先使⽤链接(即最⽼的),判断是否超时时间,如果没有超时,则必须等待try {
if (!countedWait) {
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliconds for connection.");
}
long wt = System.currentTimeMillis();
state.wait(poolTimeToWait);
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
//获得conn后,需要进⼀步判断该连接状态,包括⾮空校验等
if (conn != null) {
if (conn.isValid()) {
if (!RealConnection().getAutoCommit()) {
}
conn.tConnectionTypeCode(Url(), urname, password));
conn.tCheckoutTimestamp(System.currentTimeMillis());
conn.tLastUdTimestamp(System.currentTimeMillis());
state.activeConnections.add(conn);
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} el {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + RealHashCode() + ") was returned from the pool, getting another connection.");
}
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the databa.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the databa.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown vere error condition. The connection pool returned a null connection.");
}
throw new SQLException("PooledDataSource: Unknown vere error condition. The connection pool returned a null connection.");
}
return conn;
}
3、向连接池中push连接。
protected void pushConnection(PooledConnection conn) throws SQLException {
synchronized (state) {
ve(conn);
if (conn.isValid()) {
if (state.idleConnections.size() < poolMaximumIdleConnections && ConnectionTypeCode() == expectedConnectionTypeCode) { state.accumulatedCheckoutTime += CheckoutTime();
if (!RealConnection().getAutoCommit()) {
}
//主要⼯作是根据传⼊conn重新⽣成PooledConnection ,然后把con设置失效
PooledConnection newConn = new RealConnection(), this);
state.idleConnections.add(newConn);
newConn.CreatedTimestamp());
newConn.LastUdTimestamp());
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + RealHashCode() + " to pool.");
}
//通知其他等待连接的PooledDataSource,可以pop连接了
} el {
state.accumulatedCheckoutTime += CheckoutTime();
if (!RealConnection().getAutoCommit()) {
}
if (log.isDebugEnabled()) {
log.debug("Clod connection " + RealHashCode() + ".");
}
conn.invalidate();
}
} el {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + RealHashCode() + ") attempted to return to the pool, discarding connection.");
}
state.badConnectionCount++;
}
}
}
4、设置各种属性时都会调⽤forceCloAll()⽅法,按照注解的意思是关闭所有活动的和空闲的连接。
/*
* Clos all active and idle connections in the pool
*/
public void forceCloAll() {
synchronized (state) {
expectedConnectionTypeCode = Url(), Urname(), Password()); for (int i = state.activeConnections.size(); i > 0; i--) {
try {
PooledConnection conn = ve(i - 1);
conn.invalidate();
Connection realConn = RealConnection();
if (!AutoCommit()) {
}
realConn.clo();
} catch (Exception e) {
// ignore
}
}
for (int i = state.idleConnections.size(); i > 0; i--) {
try {
PooledConnection conn = ve(i - 1);
conn.invalidate();
Connection realConn = RealConnection();
if (!AutoCommit()) {
}
realConn.clo();
} catch (Exception e) {
// ignore
}
}
}
if (log.isDebugEnabled()) {
log.debug("PooledDataSource forcefully clod/removed all connections.");
}
}
5、获得操作数据库的实际连接,即未包装过的连接,通过动态代理⽅式获得连接对象
/*
* Unwraps a pooled connection to get to the 'real' connection
*
* @param conn - the pooled connection to unwrap
* @return The 'real' connection
*/
public static Connection unwrapConnection(Connection conn) {
if (Proxy.Class())) {
InvocationHandler handler = InvocationHandler(conn);
if (handler instanceof PooledConnection) {
return ((PooledConnection) handler).getRealConnection();
}
}
return conn;
}