从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
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);
}
}
}