dbcp源码分析-获取连接对象

入口-BasicDataSource

/**
 * Create (if necessary) and return a connection to the database.
 *
 * @throws SQLException if a database access error occurs
 * @return a database connection
 */
public Connection getConnection() throws SQLException {
    return createDataSource().getConnection();
}

获取连接的核心类

核心步骤
1.从连接池获取连接对象
2.校验连接是否有效


源码

GenericObjectPool

public T borrowObject() throws Exception {
  long starttime = System.currentTimeMillis();
  GenericObjectPool.Latch latch = new GenericObjectPool.Latch();
  byte whenExhaustedAction;
  long maxWait;

//排队处理
  synchronized(this) {
    whenExhaustedAction = this._whenExhaustedAction;
    maxWait = this._maxWait;
    this._allocationQueue.add(latch);
  }

//从连接池获取连接
  this.allocate();

  while(true) {
    synchronized(this) {
      this.assertOpen();
    }

    if (latch.getPair() == null && !latch.mayCreate()) {
      switch(whenExhaustedAction) {
      case 0:
        synchronized(this) {
          if (latch.getPair() == null && !latch.mayCreate()) {
            this._allocationQueue.remove(latch);
            throw new NoSuchElementException("Pool exhausted");
          }
          break;
        }
      case 1:
        try {
          synchronized(latch) {
            if (latch.getPair() != null || latch.mayCreate()) {
              break;
            }

            if (maxWait <= 0L) {
              latch.wait();
            } else {
              long elapsed = System.currentTimeMillis() - starttime;
              long waitTime = maxWait - elapsed;
              if (waitTime > 0L) {
                latch.wait(waitTime);
              }
            }
          }

          if (this.isClosed()) {
            throw new IllegalStateException("Pool closed");
          }
        } catch (InterruptedException var51) {
          boolean doAllocate = false;
          synchronized(this) {
            if (latch.getPair() == null && !latch.mayCreate()) {
              this._allocationQueue.remove(latch);
            } else if (latch.getPair() == null && latch.mayCreate()) {
              --this._numInternalProcessing;
              doAllocate = true;
            } else {
              --this._numInternalProcessing;
              ++this._numActive;
              this.returnObject(latch.getPair().getValue());
            }
          }

          if (doAllocate) {
            this.allocate();
          }

          Thread.currentThread().interrupt();
          throw var51;
        }

        if (maxWait <= 0L || System.currentTimeMillis() - starttime < maxWait) {
          continue;
        }

        synchronized(this) {
          if (latch.getPair() != null || latch.mayCreate()) {
            break;
          }

          this._allocationQueue.remove(latch);
        }

        throw new NoSuchElementException("Timeout waiting for idle object");
      case 2:
        synchronized(this) {
          if (latch.getPair() == null && !latch.mayCreate()) {
            this._allocationQueue.remove(latch);
            ++this._numInternalProcessing;
          }
          break;
        }
      default:
        throw new IllegalArgumentException("WhenExhaustedAction property " + whenExhaustedAction + " not recognized.");
      }
    }

    boolean newlyCreated = false;
    if (null == latch.getPair()) {
      boolean var36 = false;

      try {
        var36 = true;
        T obj = this._factory.makeObject();
        latch.setPair(new ObjectTimestampPair(obj));
        newlyCreated = true;
        var36 = false;
      } finally {
        if (var36) {
          if (!newlyCreated) {
            synchronized(this) {
              --this._numInternalProcessing;
            }

            this.allocate();
          }

        }
      }

      if (!newlyCreated) {
        synchronized(this) {
          --this._numInternalProcessing;
        }

        this.allocate();
      }
    }

//校验连接是否有效
    try {
      this._factory.activateObject(latch.getPair().value); //
      if (this._testOnBorrow && !this._factory.validateObject(latch.getPair().value)) { //校验连接是否有效
        throw new Exception("ValidateObject failed");
      }

      synchronized(this) {
        --this._numInternalProcessing;
        ++this._numActive;
      }

//返回连接对象
      return latch.getPair().value; //返回连接对象
    } catch (Throwable var47) {
      PoolUtils.checkRethrow(var47);

      try {
        this._factory.destroyObject(latch.getPair().value);
      } catch (Throwable var42) {
        PoolUtils.checkRethrow(var42);
      }

      synchronized(this) {
        --this._numInternalProcessing;
        if (!newlyCreated) {
          latch.reset();
          this._allocationQueue.add(0, latch);
        }
      }

      this.allocate();
      if (newlyCreated) {
        throw new NoSuchElementException("Could not create a validated object, cause: " + var47.getMessage());
      }
    }
  }
}

从连接池获取连接对象

真正获取连接对象的是这个方法

private CursorableLinkedList> _pool; //连接池,是一个LinkedList

//从连接池获取连接
private synchronized void allocate() {
  if (!this.isClosed()) {
    GenericObjectPool.Latch latch; //封装了连接对象
    while(!this._pool.isEmpty() && !this._allocationQueue.isEmpty()) {
      latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst(); //从排队里获取一个进行处理
      latch.setPair((ObjectTimestampPair)this._pool.removeFirst()); //从连接池获取连接对象
      ++this._numInternalProcessing;
      synchronized(latch) {
        latch.notify();
      }
    }

    while(!this._allocationQueue.isEmpty() && (this._maxActive < 0 || this._numActive + this._numInternalProcessing < this._maxActive)) {
      latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst();
      latch.setMayCreate(true);
      ++this._numInternalProcessing;
      synchronized(latch) {
        latch.notify();
      }
    }

  }
}

校验连接是否有效

public boolean validateObject(Object obj) {
  if (obj instanceof Connection) {
    try {
      this.validateConnection((Connection)obj); //校验连接是否有效
      return true; //如果连接有效,就返回true
    } catch (Exception var3) {
      return false; //如果连接无效,就返回false
    }
  } else {
    return false;
  }
}
public void validateConnection(Connection conn) throws SQLException {
  String query = this._validationQuery;
  if (conn.isClosed()) { //连接已经关闭
    throw new SQLException("validateConnection: connection closed");
  } else { //连接没有关闭,就校验连接是否有效:通过查询数据库,来校验连接是否有效
    if (null != query) {
      Statement stmt = null;
      ResultSet rset = null;

      try {
        stmt = conn.createStatement();
        if (this._validationQueryTimeout > 0) {
          stmt.setQueryTimeout(this._validationQueryTimeout);
        }

        rset = stmt.executeQuery(query);
        if (!rset.next()) {
          throw new SQLException("validationQuery didn't return a row");
        }
      } finally {
        if (rset != null) {
          try {
            rset.close();
          } catch (Exception var14) {
          }
        }

        if (stmt != null) {
          try {
            stmt.close();
          } catch (Exception var13) {
          }
        }

      }
    }

  }
}

数据结构

连接对象

封装了连接对象

private static final class Latch {
  private ObjectTimestampPair _pair;
static class ObjectTimestampPair implements Comparable {
  /** @deprecated */
  @Deprecated
  T value; //连接对象

  /** @deprecated */
  @Deprecated
  long tstamp;

连接池

private CursorableLinkedList> _pool; //是一个集合,元素是连接对象

性能

获取连接的时候,有锁

private synchronized void allocate() { //同步方法
  if (!this.isClosed()) {
    GenericObjectPool.Latch latch;
    while(!this._pool.isEmpty() && !this._allocationQueue.isEmpty()) {
      latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst();
      latch.setPair((ObjectTimestampPair)this._pool.removeFirst());
      ++this._numInternalProcessing;
      synchronized(latch) {
        latch.notify();
      }
    }

    while(!this._allocationQueue.isEmpty() && (this._maxActive < 0 || this._numActive + this._numInternalProcessing < this._maxActive)) {
      latch = (GenericObjectPool.Latch)this._allocationQueue.removeFirst();
      latch.setMayCreate(true);
      ++this._numInternalProcessing;
      synchronized(latch) {
        latch.notify();
      }
    }

  }
}

截图

1、获取连接对象
dbcp源码分析-获取连接对象_第1张图片

真正获取连接对象的方法
dbcp源码分析-获取连接对象_第2张图片

2、校验连接是否有效
dbcp源码分析-获取连接对象_第3张图片

dbcp和pool

dbcp是基于pool,底层的连接池都是pool实现的。

你可能感兴趣的:(dbcp,数据库连接池)