C3P0 连接分析

最近在看C3P0的原理,还是将C3P0的源码导入到Ecplise中debug看得清楚多了。下面记录我debug的经历。

1. 下载c3p0的jar和源码,这个百度吧。
2. 导入jar和源码到java工程中,导入后,会发现有些错误的,把junit的类去掉,有的提示没有实现一些方法,就加进去,还有的提示要删除多余的实现方法,就删除掉吧,这样下来,基本上不报错了。
3. debug的过程中,有些类没有源码的,到google上去搜,会有源码的,写一个对应的java类加进工程里去就行了。

1. 写一个连接池的简单的工具类


public class ConnectionPool {
private static ComboPooledDataSource ds;
public synchronized static final Connection getConnection() {
try {
if (ds != null) {
return ds.getConnection();
}
else{
ds = new ComboPooledDataSource(true);
ds.setJdbcUrl("jdbc:mysql://192.168.1.102:3306/S10");
try {
ds.setDriverClass("com.mysql.jdbc.Driver");
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ds.setUser("root");
ds.setPassword("123456");
ds.setInitialPoolSize(10);
ds.setMinPoolSize(10);
ds.setMaxPoolSize(20);
ds.setMaxIdleTime(30);

return ds.getConnection();
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}



2. 现在需要debug的代码是
ds.getConnection()
,看看它的执行顺序吧。

首先进入的是AbstractPoolBackedDataSource中的getConnection方法

pc = getPoolManager().getPool().checkoutPooledConnection();
return pc.getConnection();


其中:getPoolManager().getPool()是获取连接池,它对应的类是C3P0PooledConnectionPoolManager,它管理着连接池的生命周期。

C3P0PooledConnectionPoolManager中有一个内部类PooledConnectionResourcePoolManager,它里面会创建BasicResourcePool,BasicResourcePool才是真正创建连接的地方。

会调用里面的私有方法。


private void _recheckResizePool()
{
assert Thread.holdsLock(this);

if (! broken)
{
int msz = managed.size();

int shrink_count;
int expand_count;

if ((shrink_count = msz - pending_removes - target_pool_size) > 0)
shrinkPool( shrink_count );
else if ((expand_count = target_pool_size - (msz + pending_acquires)) > 0)
expandPool( expand_count );
}
}


继续跟踪expandPool()方法,这里的expand_count 是初始值10.


private void expandPool(int count)
{
assert Thread.holdsLock(this);

// XXX: temporary switch -- assuming no problems appear, we'll get rid of AcquireTask
// in favor of ScatteredAcquireTask
if ( USE_SCATTERED_ACQUIRE_TASK )
{
for (int i = 0; i < count; ++i)
taskRunner.postRunnable( new ScatteredAcquireTask() );
}
else
{
for (int i = 0; i < count; ++i)
taskRunner.postRunnable( new AcquireTask() );
}
}


进入到AcquireTask()方法里看到如下的代码。


BasicResourcePool.this.doAcquire();

Object resc = mgr.acquireResource();



acquireResource()方法会调用一个内部类PooledConnectionResourcePoolManager,它会调用下面的代码。


if ( connectionCustomizer == null)
{
out = (auth.equals( C3P0ImplUtils.NULL_AUTH ) ?
cpds.getPooledConnection() :
cpds.getPooledConnection( auth.getUser(),
auth.getPassword() ) );
}


上面的代码调用下面的代码


protected PooledConnection getPooledConnection(String user, String password, ConnectionCustomizer cc, String pdsIdt)
throws SQLException
{
// 它里面包含jdbcUrl等信息
DataSource nds = getNestedDataSource();
if (nds == null)
throw new SQLException( "No standard DataSource has been set beneath this wrapper! [ nestedDataSource == null ]");
// 这里的代码调用是在DriverManagerDataSource中实现的
Connection conn = nds.getConnection(user, password);
if (conn == null)
throw new SQLException("An (unpooled) DataSource returned null from its getConnection() method! " +
"DataSource: " + getNestedDataSource());
if ( this.isUsesTraditionalReflectiveProxies() )
{
//return new C3P0PooledConnection( new com.mchange.v2.c3p0.test.CloseReportingConnection( conn ),
return new C3P0PooledConnection( conn,
connectionTester,
this.isAutoCommitOnClose(),
this.isForceIgnoreUnresolvedTransactions(),
cc,
pdsIdt);
}
else
{
return new NewPooledConnection( conn,
connectionTester,
this.isAutoCommitOnClose(),
this.isForceIgnoreUnresolvedTransactions(),
this.getPreferredTestQuery(),
cc,
pdsIdt);
}
}



public Connection getConnection(String username, String password) throws SQLException
{
ensureDriverLoaded();
// 这才是真实的物理连接啊
Connection out = driver().connect( jdbcUrl, overrideProps(username, password) );
if (out == null)
throw new SQLException("Apparently, jdbc URL '" + jdbcUrl + "' is not valid for the underlying " +
"driver [" + driver() + "].");
return out;
}


至此,初始化的10个连接完成了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值