//
// mybatis的数据源
//
package org.apache.ibatis.datasource.pooled;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
public class PooledDataSource implements DataSource {
private static final Log log = LogFactory.getLog(PooledDataSource.class);
private final PoolState state = new PoolState(this);
private final UnpooledDataSource dataSource;
//连接池最大连接数
protected int poolMaximumActiveConnections = 10;
//连接池最大闲置连接数
protected int poolMaximumIdleConnections = 5;
//连接池最大检测时间
protected int poolMaximumCheckoutTime = 20000;
//连接池等待时间
protected int poolTimeToWait = 20000;
protected int poolMaximumLocalBadConnectionTolerance = 3;
protected String poolPingQuery = "NO PING QUERY SET";
protected boolean poolPingEnabled;
protected int poolPingConnectionsNotUsedFor;
private int expectedConnectionTypeCode;
//构造方法
public PooledDataSource() {
this.dataSource = new UnpooledDataSource();
}
public PooledDataSource(UnpooledDataSource dataSource) {
this.dataSource = dataSource;
}
public PooledDataSource(String driver, String url, String username, String password) {
this.dataSource = new UnpooledDataSource(driver, url, username, password);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(String driver, String url, Properties driverProperties) {
this.dataSource = new UnpooledDataSource(driver, url, driverProperties);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, username, password);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, driverProperties);
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
}
//获取连接
public Connection getConnection() throws SQLException {
return this.popConnection(this.dataSource.getUsername(), this.dataSource.getPassword()).getProxyConnection();
}
public Connection getConnection(String username, String password) throws SQLException {
return this.popConnection(username, password).getProxyConnection();
}
public void setLoginTimeout(int loginTimeout) {
DriverManager.setLoginTimeout(loginTimeout);
}
public int getLoginTimeout() {
return DriverManager.getLoginTimeout();
}
public void setLogWriter(PrintWriter logWriter) {
DriverManager.setLogWriter(logWriter);
}
public PrintWriter getLogWriter() {
return DriverManager.getLogWriter();
}
public void setDriver(String driver) {
this.dataSource.setDriver(driver);
this.forceCloseAll();
}
public void setUrl(String url) {
this.dataSource.setUrl(url);
this.forceCloseAll();
}
public void setUsername(String username) {
this.dataSource.setUsername(username);
this.forceCloseAll();
}
public void setPassword(String password) {
this.dataSource.setPassword(password);
this.forceCloseAll();
}
public void setDefaultAutoCommit(boolean defaultAutoCommit) {
this.dataSource.setAutoCommit(defaultAutoCommit);
this.forceCloseAll();
}
public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
this.dataSource.setDefaultTransactionIsolationLevel(defaultTransactionIsolationLevel);
this.forceCloseAll();
}
public void setDriverProperties(Properties driverProps) {
this.dataSource.setDriverProperties(driverProps);
this.forceCloseAll();
}
public void setDefaultNetworkTimeout(Integer milliseconds) {
this.dataSource.setDefaultNetworkTimeout(milliseconds);
this.forceCloseAll();
}
public void setPoolMaximumActiveConnections(int poolMaximumActiveConnections) {
this.poolMaximumActiveConnections = poolMaximumActiveConnections;
this.forceCloseAll();
}
public void setPoolMaximumIdleConnections(int poolMaximumIdleConnections) {
this.poolMaximumIdleConnections = poolMaximumIdleConnections;
this.forceCloseAll();
}
public void setPoolMaximumLocalBadConnectionTolerance(int poolMaximumLocalBadConnectionTolerance) {
this.poolMaximumLocalBadConnectionTolerance = poolMaximumLocalBadConnectionTolerance;
}
public void setPoolMaximumCheckoutTime(int poolMaximumCheckoutTime) {
this.poolMaximumCheckoutTime = poolMaximumCheckoutTime;
this.forceCloseAll();
}
public void setPoolTimeToWait(int poolTimeToWait) {
this.poolTimeToWait = poolTimeToWait;
this.forceCloseAll();
}
public void setPoolPingQuery(String poolPingQuery) {
this.poolPingQuery = poolPingQuery;
this.forceCloseAll();
}
public void setPoolPingEnabled(boolean poolPingEnabled) {
this.poolPingEnabled = poolPingEnabled;
this.forceCloseAll();
}
public void setPoolPingConnectionsNotUsedFor(int milliseconds) {
this.poolPingConnectionsNotUsedFor = milliseconds;
this.forceCloseAll();
}
public String getDriver() {
return this.dataSource.getDriver();
}
public String getUrl() {
return this.dataSource.getUrl();
}
public String getUsername() {
return this.dataSource.getUsername();
}
public String getPassword() {
return this.dataSource.getPassword();
}
public boolean isAutoCommit() {
return this.dataSource.isAutoCommit();
}
public Integer getDefaultTransactionIsolationLevel() {
return this.dataSource.getDefaultTransactionIsolationLevel();
}
public Properties getDriverProperties() {
return this.dataSource.getDriverProperties();
}
public Integer getDefaultNetworkTimeout() {
return this.dataSource.getDefaultNetworkTimeout();
}
public int getPoolMaximumActiveConnections() {
return this.poolMaximumActiveConnections;
}
public int getPoolMaximumIdleConnections() {
return this.poolMaximumIdleConnections;
}
public int getPoolMaximumLocalBadConnectionTolerance() {
return this.poolMaximumLocalBadConnectionTolerance;
}
public int getPoolMaximumCheckoutTime() {
return this.poolMaximumCheckoutTime;
}
public int getPoolTimeToWait() {
return this.poolTimeToWait;
}
public String getPoolPingQuery() {
return this.poolPingQuery;
}
public boolean isPoolPingEnabled() {
return this.poolPingEnabled;
}
public int getPoolPingConnectionsNotUsedFor() {
return this.poolPingConnectionsNotUsedFor;
}
//强制关闭所有连接
public void forceCloseAll() {
PoolState var1 = this.state;
synchronized(this.state) {
this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
int i;
PooledConnection conn;
Connection realConn;
for(i = this.state.activeConnections.size(); i > 0; --i) {
try {
conn = (PooledConnection)this.state.activeConnections.remove(i - 1);
conn.invalidate();
realConn = conn.getRealConnection();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
realConn.close();
} catch (Exception var7) {
;
}
}
for(i = this.state.idleConnections.size(); i > 0; --i) {
try {
conn = (PooledConnection)this.state.idleConnections.remove(i - 1);
conn.invalidate();
realConn = conn.getRealConnection();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
realConn.close();
} catch (Exception var6) {
;
}
}
}
if (log.isDebugEnabled()) {
log.debug("PooledDataSource forcefully closed/removed all connections.");
}
}
//获取连接池状态
public PoolState getPoolState() {
return this.state;
}
//获取连接的哈希码
private int assembleConnectionTypeCode(String url, String username, String password) {
return ("" + url + username + password).hashCode();
}
//归还连接池的连接
protected void pushConnection(PooledConnection conn) throws SQLException {
PoolState var2 = this.state;
synchronized(this.state) {
this.state.activeConnections.remove(conn);
if (conn.isValid()) {
if (this.state.idleConnections.size() < this.poolMaximumIdleConnections && conn.getConnectionTypeCode() == this.expectedConnectionTypeCode) {
this.state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
this.state.idleConnections.add(newConn);
newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
}
this.state.notifyAll();
} else {
this.state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.getRealConnection().close();
if (log.isDebugEnabled()) {
log.debug("Closed connection " + conn.getRealHashCode() + ".");
}
conn.invalidate();
}
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
}
++this.state.badConnectionCount;
}
}
}
//弹出一个连接
private PooledConnection popConnection(String username, String password) throws SQLException {
boolean countedWait = false;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
while(conn == null) {
//PoolState 记录了连接池状态
PoolState var8 = this.state;
synchronized(this.state) {
//闲置的连接不为空时,返回一个连接
if (!this.state.idleConnections.isEmpty()) {
//闲置连接List中移除一个记录
conn = (PooledConnection)this.state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) {
//闲置连接为0但是活跃连接小于最大活跃数时,生成一个连接
conn = new PooledConnection(this.dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
//闲置连接为0但是活跃连接不小于最大活跃数时
PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) {
++this.state.claimedOverdueConnectionCount;
this.state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
this.state.accumulatedCheckoutTime += longestCheckoutTime;
this.state.activeConnections.remove(oldestActiveConnection);
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException var15) {
log.debug("Bad connection. Could not roll back");
}
}
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
try {
if (!countedWait) {
++this.state.hadToWaitCount;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + this.poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
this.state.wait((long)this.poolTimeToWait);
this.state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException var16) {
break;
}
}
}
if (conn != null) {
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(this.assembleConnectionTypeCode(this.dataSource.getUrl(), username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
this.state.activeConnections.add(conn);
++this.state.requestCount;
this.state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
++this.state.badConnectionCount;
++localBadConnectionCount;
conn = null;
if (localBadConnectionCount > this.poolMaximumIdleConnections + this.poolMaximumLocalBadConnectionTolerance) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
} else {
return conn;
}
}
//ping连接??
protected boolean pingConnection(PooledConnection conn) {
boolean result = true;
try {
result = !conn.getRealConnection().isClosed();
} catch (SQLException var21) {
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + var21.getMessage());
}
result = false;
}
if (result && this.poolPingEnabled && this.poolPingConnectionsNotUsedFor >= 0 && conn.getTimeElapsedSinceLastUse() > (long)this.poolPingConnectionsNotUsedFor) {
try {
if (log.isDebugEnabled()) {
log.debug("Testing connection " + conn.getRealHashCode() + " ...");
}
Connection realConn = conn.getRealConnection();
Statement statement = realConn.createStatement();
Throwable var5 = null;
try {
statement.executeQuery(this.poolPingQuery).close();
} catch (Throwable var18) {
var5 = var18;
throw var18;
} finally {
if (statement != null) {
if (var5 != null) {
try {
statement.close();
} catch (Throwable var17) {
var5.addSuppressed(var17);
}
} else {
statement.close();
}
}
}
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
result = true;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
}
} catch (Exception var20) {
log.warn("Execution of ping query '" + this.poolPingQuery + "' failed: " + var20.getMessage());
try {
conn.getRealConnection().close();
} catch (Exception var16) {
;
}
result = false;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + var20.getMessage());
}
}
}
return result;
}
public static Connection unwrapConnection(Connection conn) {
if (Proxy.isProxyClass(conn.getClass())) {
InvocationHandler handler = Proxy.getInvocationHandler(conn);
if (handler instanceof PooledConnection) {
return ((PooledConnection)handler).getRealConnection();
}
}
return conn;
}
//实现资源清理工作:关闭连接池,垃圾回收(不可靠的)
protected void finalize() throws Throwable {
this.forceCloseAll();
super.finalize();
}
public <T> T unwrap(Class<T> iface) throws SQLException {
throw new SQLException(this.getClass().getName() + " is not a wrapper.");
}
public boolean isWrapperFor(Class<?> iface) {
return false;
}
public Logger getParentLogger() {
return Logger.getLogger("global");
}
}
mybatis的默认数据源
最新推荐文章于 2024-11-27 22:06:37 发布