前面,我们已经找到了真正的DataSource,这个类就是PoolingDataSource ,
同时,也找到了对象状态维护工厂PoolableConnectionFactory目前不用急于往下看代码,如果再继续看,就容易晕,先从整体上思考一下,既然DBCP可以处理我们没有关闭的连接,那么,它的一定有自己的对象池,而且必须继承自GenericObjectPool,我们根据GenericObjectPool进行搜索,就找到了AbandonedObjectPool这个核心的连接池。
AbandonedObjectPool有一个配置文件属性,也就是AbandonedConfig类的对象,我们先看看这个类包括了哪些属性(这些属性非常重要,我们今后可能不会去写DBCP,但要使用DBCP就必须配置这些属性):
public class AbandonedConfig {
//是否移除超时不使用的连接
private boolean removeAbandoned = false;
//超时时间
private int removeAbandonedTimeout = 300;
//是否记录日志
private boolean logAbandoned = false;
//日志对象
private PrintWriter logWriter = newPrintWriter(System.out);
//省略GET\SET方法一批
}
再来看看AbandonedObjectPool类:
public class AbandonedObjectPool extends GenericObjectPool {
//DBCP配置对象
private final AbandonedConfig config;
//使用中的连接
private final List trace = new ArrayList();
public AbandonedObjectPool(PoolableObjectFactoryfactory,
AbandonedConfig config) {
super(factory);
this.config = config;
}
//从连接池中取出对象
public Object borrowObject() throws Exception {
if (config != null
&& config.getRemoveAbandoned()
&& (getNumIdle() <2)//空闲连接小于2
&& (getNumActive() >getMaxActive() - 3) ) {
//借出的连接大于最大连接-3
//即借出的+空闲的大于等于最大连接数
removeAbandoned();//移除连接,在这个方法里面判断是否超时
}
Object obj = super.borrowObject();
if (obj instanceof AbandonedTrace) {
((AbandonedTrace)obj).setStackTrace();
}
if (obj != null && config != null && config.getRemoveAbandoned()) {
synchronized (trace) {
trace.add(obj);
}
}
return obj;
}
/**
* 移除没有使用的超时连接
*
*/
private void removeAbandoned() {
// Generate a list of abandoned connections to remove
long now = System.currentTimeMillis();
long timeout = now - (config.getRemoveAbandonedTimeout() * 1000);//当前时间-超时时间*1000),得到过去的某个时间点,在此时间点之前就是超时
ArrayList remove = new ArrayList();//用于保存需要移除的连接
synchronized (trace) {
Iterator it = trace.iterator();
while (it.hasNext()) {
AbandonedTrace pc =(AbandonedTrace) it.next();//注意, AbandonedTrace很重要,是继承Connection接口,是所有代理Connection的基类
if (pc.getLastUsed() > timeout) {//不超时
continue;
}
if (pc.getLastUsed() > 0) {//超时的,而且最近有使用过
remove.add(pc);
}
}
}
Iterator it = remove.iterator();
while (it.hasNext()) {
AbandonedTrace pc =(AbandonedTrace) it.next();
if (config.getLogAbandoned()) {
pc.printStackTrace();
}
try {
invalidateObject(pc);//将连接设置为无效
} catch (Exception e) {
e.printStackTrace();
}
}
}
//归还对象,没有什么可说
public void returnObject(Object obj) throws Exception {
if (config != null && config.getRemoveAbandoned()) {
synchronized (trace) {
boolean foundObject = trace.remove(obj);
if (!foundObject) {
return; // This connection has already been invalidated. Stop now.
}
}
}
super.returnObject(obj);
}
public void invalidateObject(Object obj) throws Exception {
if (config != null && config.getRemoveAbandoned()) {
synchronized (trace) {
boolean foundObject = trace.remove(obj);
if (!foundObject) {
return; // This connection has already been invalidated. Stop now.
}
}
}
super.invalidateObject(obj); //看到没有,实际上是调用父类来将其设置为无效的
}
}
我们知道,我们自己使用对象池时,需要传递一个对象状态维护工厂,这个工厂继承PoolableObjectFactory接口,在该工厂中,实现对连接的真正维护,通过前面的学习,我们找到了该对象状态工厂类就是: PoolableConnectionFactory,再来看看这个类的代码:
public class PoolableConnectionFactoryimplements PoolableObjectFactory {
//省略构造函数一大批
protected volatile ConnectionFactory _connFactory = null;
protected volatile String _validationQuery = null;//验证的SQL
protected volatile int _validationQueryTimeout = -1;//验证的超时时间
protected Collection _connectionInitSqls = null;//连接成功的初始化语句
protected volatile ObjectPool _pool = null;
protected volatile KeyedObjectPoolFactory _stmtPoolFactory = null;
protected Boolean _defaultReadOnly = null;//默认是否只读
protected boolean _defaultAutoCommit = true;//是否自动提交(true即不启动事务)
protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;//默认数据库隔离级别
protected String _defaultCatalog;//默认数据库名称
protected AbandonedConfig _config = null;
static final int UNKNOWN_TRANSACTIONISOLATION = -1;
//这里省略对属性进行Get、Set的方法一批
//创建对象
public Object makeObject() throws Exception {
Connection conn = _connFactory.createConnection();
if (conn == null) {
throw new IllegalStateException("Connection factory returned null from createConnection");
}
initializeConnection(conn);//初始化连接,即生成连接并尝试去执行SQL
if(null != _stmtPoolFactory) {
KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
conn = newPoolingConnection(conn,stmtpool);//这个连接是对真正Connection的进一步封装,注意,这个类是后面的重点。
stmtpool.setFactory((PoolingConnection)conn);
}
return new PoolableConnection(conn,_pool,_config);
}
//初始化连接
protected void initializeConnection(Connection conn) throws SQLException {
Collection sqls = _connectionInitSqls;
if(conn.isClosed()) {
throw new SQLException("initializeConnection:connection closed");
}
if(null != sqls) {
Statement stmt = null;
try {
stmt = conn.createStatement();
for (Iterator iterator = sqls.iterator();iterator.hasNext();)
{
Object o = iterator.next();
if (o == null) {
throw new NullPointerException("null connectionInitSqls element");
}
// o might not be a String instance
String sql = o.toString();
stmt.execute(sql);
}
} finally {
if (stmt != null) {
try {
stmt.close();
} catch(Exception t) {
// ignored
}
}
}
}
}
//销毁连接
public void destroyObject(Object obj) throws Exception {
if(obj instanceof PoolableConnection) {
((PoolableConnection)obj).reallyClose();//看来,有真正的关闭也有假的关闭啊,假的关闭多半就是close方法
}
}
//验证对象
public boolean validateObject(Object obj) {
if(obj instanceof Connection) {
try {
validateConnection((Connection)obj);
return true;
} catch(Exception e) {
return false;
}
} else {
return false;
}
}
//验证连接,实际就是执行我们传递进来的SQL
public void validateConnection(Connection conn) throws SQLException {
String query = _validationQuery;
if(conn.isClosed()) {
throw new SQLException("validateConnection:connection closed");
}
if(null != query) {
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
if (_validationQueryTimeout > 0) {
stmt.setQueryTimeout(_validationQueryTimeout);
}
rset =stmt.executeQuery(query);
if(!rset.next()) {
throw new SQLException("validationQuerydidn't return a row");
}
} finally {
if (rset != null) {
try {
rset.close();
} catch(Exception t) {
// ignored
}
}
if (stmt != null) {
try {
stmt.close();
} catch(Exception t) {
// ignored
}
}
}
}
}
//归还对象执行动作
public void passivateObject(Object obj) throws Exception {
if(obj instanceof Connection){
Connection conn = (Connection)obj;
if(!conn.getAutoCommit() &&!conn.isReadOnly()) {
conn.rollback();
}
conn.clearWarnings();
if(!conn.getAutoCommit()) {
conn.setAutoCommit(true);
}
}
if(obj instanceof DelegatingConnection) {
((DelegatingConnection)obj).passivate();
}
}
//激活对象
public void activateObject(Object obj) throws Exception {
if(obj instanceof DelegatingConnection) {
((DelegatingConnection)obj).activate();
}
if(obj instanceof Connection) {
Connection conn = (Connection)obj;
if (conn.getAutoCommit() != _defaultAutoCommit) {
conn.setAutoCommit(_defaultAutoCommit);
}
if ((_defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION)
&&(conn.getTransactionIsolation() !=
_defaultTransactionIsolation)) {
conn.setTransactionIsolation(_defaultTransactionIsolation);
}
if ((_defaultReadOnly != null) &&
(conn.isReadOnly() != _defaultReadOnly.booleanValue())){
conn.setReadOnly(_defaultReadOnly.booleanValue());
}
if ((_defaultCatalog != null) &&
(!_defaultCatalog.equals(conn.getCatalog()))) {
conn.setCatalog(_defaultCatalog);
}
}
}
}