您的位置:首页 > 数据库

数据库连接池DBCP框架的研究以及源代码分析二:寻找真正的DataSource

2013-04-24 22:15 351 查看
从DataSourceFactory中,我们看到DataSourceFactory创建了一个DataBaseSource,如下代码

public static DataSource createDataSource(Properties properties) throws Exception {

BasicDataSource dataSource = new BasicDataSource();

//省略设置属性若干

retrun dataSource ;

}

那么BasicDatasource是什么东东?请看代码

public class BasicDataSource implements DataSource {//从这里看,好像这个类就是传说中的DataSource,但是看看下面的红色属性部分

static {

DriverManager.getDrivers();//注册驱动

}

//这里省略SET\GET方法一堆,以免耽误代价时间,直接看属性

protected volatile DataSource dataSource = null;//这里又定义了一个Datasource,看来BasicDataSource只是一个烟雾弹,在里面的属性,才是真正的DataSource,我们知道,DataSource接口主要是用于创建连接,那么我们看一下getConnection()就可以确认我们的猜测是否正确?,继续往下看红色部分

protected volatile boolean defaultAutoCommit = true;

protected transient Boolean defaultReadOnly = null;

protected volatile int defaultTransactionIsolation =

PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION;

protected volatile String defaultCatalog = null;

protected String driverClassName = null;

protected ClassLoader driverClassLoader = null;

protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;

protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;

protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;

protected int initialSize = 0;

protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;

protected boolean poolPreparedStatements = false;

protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;

protected boolean testOnBorrow = true;

protected boolean testOnReturn = false;

protected long timeBetweenEvictionRunsMillis =

GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;

protected int numTestsPerEvictionRun =

GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;

protected long minEvictableIdleTimeMillis =

GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;

protected boolean testWhileIdle = false;

protected volatile String password = null;

protected String url = null;

protected String username = null;

protected volatile String validationQuery = null;//验证连接有效性的SQL

protected volatile int validationQueryTimeout = -1;

protected volatile List connectionInitSqls;

private boolean accessToUnderlyingConnectionAllowed = false; //是否可以操作底层连接

private volatile boolean restartNeeded = false;

protected volatile GenericObjectPool connectionPool = null;
//连接池

protected Properties connectionProperties = new Properties();

protected PrintWriter logWriter = new PrintWriter(System.out);

private AbandonedConfig abandonedConfig;

protected boolean closed;

public Connection getConnection() throws SQLException {

return createDataSource().getConnection();//看来,这个类很狡猾,跟我们玩了一个花样,createDataSource里面创建的才是真正创造连接的DataSource接口

}

//创建真正DataSource的类

protected synchronized DataSource createDataSource()//核心方法

throws SQLException {

if (closed) {

throw new SQLException("Data source is closed");

}

// 如果已经创建过一次了,就返回已经创建的,这个合情合理

if (dataSource != null) {

return (dataSource);

}

// 创建一个工厂,用于生成真正物理的Connection

ConnectionFactory driverConnectionFactory = createConnectionFactory();

// 创建我们的连接池

createConnectionPool();

GenericKeyedObjectPoolFactory statementPoolFactory = null;

if (isPoolPreparedStatements()) {//如果需要缓存PrepareStatement,生成带KEY的对象池

statementPoolFactory = new GenericKeyedObjectPoolFactory(null,

-1, // unlimited maxActive (per key)

GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,

0, // maxWait

1, // maxIdle (per key)

maxOpenPreparedStatements);

}

// 创建对象状态维护工厂类

createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig);

// 创建真正的DataSource来管理连接

createDataSourceInstance();

try {//初始化对象

for (int i = 0 ; i < initialSize ; i++) {

connectionPool.addObject();

}

} catch (Exception e) {

throw new SQLNestedException("Error preloading the connection pool", e);

}

return dataSource;

}

/**

* 创建Connection工厂

*/

protected ConnectionFactory createConnectionFactory() throws SQLException {

// 注册驱动

Class driverFromCCL = null;

if (driverClassName != null) {

try {

try {

if (driverClassLoader == null) {

Class.forName(driverClassName);

} else {

Class.forName(driverClassName, true, driverClassLoader);

}

} catch (ClassNotFoundException cnfe) {

driverFromCCL = Thread.currentThread(

).getContextClassLoader().loadClass(

driverClassName);

}

} catch (Throwable t) {

String message = "Cannot load JDBC driver class '" +

driverClassName + "'";

logWriter.println(message);

t.printStackTrace(logWriter);

throw new SQLNestedException(message, t);

}

}

// 创建Driver实例

Driver driver = null;

try {

if (driverFromCCL == null) {

driver = DriverManager.getDriver(url);

} else {

// Usage of DriverManager is not possible, as it does not

// respect the ContextClassLoader

driver = (Driver) driverFromCCL.newInstance();

if (!driver.acceptsURL(url)) {

throw new SQLException("No suitable driver", "08001");

}

}

} catch (Throwable t) {

String message = "Cannot create JDBC driver of class '" +

(driverClassName != null ? driverClassName : "") +

"' for connect URL '" + url + "'";

logWriter.println(message);

t.printStackTrace(logWriter);

throw new SQLNestedException(message, t);

}

// 根据验证的SQL语句判断是否需要验证连接有效性

if (validationQuery == null) {

setTestOnBorrow(false);

setTestOnReturn(false);

setTestWhileIdle(false);

}

// Set up the driver connection factory we will use

String user = username;

if (user != null) {

connectionProperties.put("user", user);

} else {

log("DBCP DataSource configured without a 'username'");

}

String pwd = password;

if (pwd != null) {

connectionProperties.put("password", pwd);

} else {

log("DBCP DataSource configured without a 'password'");

}

ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driver, url, connectionProperties);

return driverConnectionFactory;

}

/**

*创建连接池

*/

protected void createConnectionPool() {

GenericObjectPool gop;

if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned())) {//如果有配置以及设置收回没有使用的连接

gop = new AbandonedObjectPool(null,abandonedConfig);//生成我们带回收连接的连接池

}

else {

gop = new GenericObjectPool();//生成普通连接池

}

gop.setMaxActive(maxActive);

gop.setMaxIdle(maxIdle);

gop.setMinIdle(minIdle);

gop.setMaxWait(maxWait);

gop.setTestOnBorrow(testOnBorrow);

gop.setTestOnReturn(testOnReturn);

gop.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);

gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

gop.setTestWhileIdle(testWhileIdle);

connectionPool = gop;

}

/**

创建可池化连接工厂(对象状态维护工厂)

*/

protected void createPoolableConnectionFactory(ConnectionFactory driverConnectionFactory,

KeyedObjectPoolFactory statementPoolFactory, AbandonedConfig configuration) throws SQLException {

PoolableConnectionFactory connectionFactory = null;

try {

//由此我们可以看到,对象状态维护工厂为PoolableConnectionFactory,提供了makeObject,Destory等方法对对象进行维护。

connectionFactory =

new PoolableConnectionFactory(driverConnectionFactory,/

connectionPool,

statementPoolFactory,

validationQuery,

validationQueryTimeout,

connectionInitSqls,

defaultReadOnly,

defaultAutoCommit,

defaultTransactionIsolation,

defaultCatalog,

configuration);

validateConnectionFactory(connectionFactory);

} catch (RuntimeException e) {

throw e;

} catch (Exception e) {

throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);

}

}

protected void createDataSourceInstance() throws SQLException {

PoolingDataSource pds = new PoolingDataSource(connectionPool);//真正的Datasource对象,看来我们找到了,值得庆祝一下,慢慢抽丝剥茧读代码

pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());

pds.setLogWriter(logWriter);

dataSource = pds;

}

--------------------------------------------------------核心代码到此完,下面的方法,即使不用脑子,用脚趾也能猜出是干嘛的--------------------------

public Connection getConnection(String user, String pass) throws SQLException {

throw new UnsupportedOperationException("Not supported by BasicDataSource");

}

public int getLoginTimeout() throws SQLException {

throw new UnsupportedOperationException("Not supported by BasicDataSource");

}

public PrintWriter getLogWriter() throws SQLException {

return createDataSource().getLogWriter();

}

public void setLoginTimeout(int loginTimeout) throws SQLException {

throw new UnsupportedOperationException("Not supported by BasicDataSource");

}

public void setLogWriter(PrintWriter logWriter) throws SQLException {

createDataSource().setLogWriter(logWriter);

this.logWriter = logWriter;

}

public boolean getRemoveAbandoned() {

if (abandonedConfig != null) {

return abandonedConfig.getRemoveAbandoned();

}

return false;

}

public void setRemoveAbandoned(boolean removeAbandoned) {

if (abandonedConfig == null) {

abandonedConfig = new AbandonedConfig();

}

abandonedConfig.setRemoveAbandoned(removeAbandoned);

this.restartNeeded = true;

}

public int getRemoveAbandonedTimeout() {

if (abandonedConfig != null) {

return abandonedConfig.getRemoveAbandonedTimeout();

}

return 300;

}

public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {

if (abandonedConfig == null) {

abandonedConfig = new AbandonedConfig();

}

abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);

this.restartNeeded = true;

}

public boolean getLogAbandoned() {

if (abandonedConfig != null) {

return abandonedConfig.getLogAbandoned();

}

return false;

}

public void setLogAbandoned(boolean logAbandoned) {

if (abandonedConfig == null) {

abandonedConfig = new AbandonedConfig();

}

abandonedConfig.setLogAbandoned(logAbandoned);

this.restartNeeded = true;

}

//公用方法

public void addConnectionProperty(String name, String value) {

connectionProperties.put(name, value);

this.restartNeeded = true;

}

public void removeConnectionProperty(String name) {

connectionProperties.remove(name);

this.restartNeeded = true;

}

public void setConnectionProperties(String connectionProperties) {

if (connectionProperties == null) throw new NullPointerException("connectionProperties is null");

String[] entries = connectionProperties.split(";");

Properties properties = new Properties();

for (int i = 0; i < entries.length; i++) {

String entry = entries[i];

if (entry.length() > 0) {

int index = entry.indexOf('=');

if (index > 0) {

String name = entry.substring(0, index);

String value = entry.substring(index + 1);

properties.setProperty(name, value);

} else {

// no value is empty string which is how java.util.Properties works

properties.setProperty(entry, "");

}

}

}

this.connectionProperties = properties;

this.restartNeeded = true;

}

//关闭连接池

public synchronized void close() throws SQLException {

closed = true;

GenericObjectPool oldpool = connectionPool;

connectionPool = null;

dataSource = null;

try {

if (oldpool != null) {

oldpool.close();

}

} catch(SQLException e) {

throw e;

} catch(RuntimeException e) {

throw e;

} catch(Exception e) {

throw new SQLNestedException("Cannot close connection pool", e);

}

}

public synchronized boolean isClosed() {

return closed;

}

public boolean isWrapperFor(Class<?> iface) throws SQLException {

return false;

}

public <T> T unwrap(Class<T> iface) throws SQLException {

throw new SQLException("BasicDataSource is not a wrapper.");

}

protected static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception {

Connection conn = null;

try {

conn = (Connection) connectionFactory.makeObject();

connectionFactory.activateObject(conn);

connectionFactory.validateConnection(conn);

connectionFactory.passivateObject(conn);

}

finally {

connectionFactory.destroyObject(conn);

}

}

/**

* Not used currently

*/

private void restart() {

try {

close();

} catch (SQLException e) {

log("Could not restart DataSource, cause: " + e.getMessage());

}

}

protected void log(String message) {

if (logWriter != null) {

logWriter.println(message);

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐