本文共 2666 字,大约阅读时间需要 8 分钟。
使用的设计模式:动态代理,静态代理
1.UnpooledDataSourceFactory 非池化数据源工厂:
setProperties 解析配置文件
46行MetaObject metaDataSource = SystemMetaObject.forObject(dataSource); 获取数据源对象的元对象
convertValue 根据根据属性类型对配置的值进行转换
2.UnpooledDataSource 非池化的数据源 此类只是简单的封装了JDBC
doGetConnection 获取连接
1.initializeDriver 初始化驱动
2.DriverManager.getConnection 获取连接
3.configureConnection 设置超时,事务和事务隔离级别
内部类:DriverProxy 使用静态代理的方式代理驱动
#########################################################################
3.PooledDataSourceFactory 池化的数据源工厂
继承非池化的数据源 对配置文件的处理和非池化的工厂一样
4.PooledDataSource 池化的数据源
为保证线程安全,下面几个操作都是使用synchronized,锁的对象是state
4.1 forceCloseAll 关闭所有连接
先处理正在使用的连接,再处理空闲的连接
a.此处的关闭并不是直接将连接对象关闭,而是将valid标识设置为false,每次连接被使用的时候都会去校验(isValid方法)此属性是否可用,从而达到关闭连接的作用,关闭连接之后会根据当前事务是否为手动事务来判断是否回滚当前事务
b.关闭真实的连接
c.对空闲的连接重复上述动作
4.2 pushConnection 归还连接
4.2.1 当空闲连接数小于最大连接数时,先回滚当前手动事务,再重新创建一个池化的连接对象,将原有的真实连接传递给新对象,并放入空闲的连接数组中,关闭原有连接,关闭方式也是关闭开关。
4.2.2 当空闲连接数大于最大连接数时,直接关闭当前连接
4.3 popConnection 获取连接
4.3.1 先检测空闲数组中是否有空闲关掉,取连接总是从空闲连接数组中取第一个 模拟队列
conn = state.idleConnections.remove(0);
4.3.2 如果没有连接时空闲的,那么判断当前正在使用的连接数是否小于最大连接数,如果满足则直接初始化一个新的连接对象,
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
conn = new PooledConnection(dataSource.getConnection(), this);
}
}
如果不满足,就进行等待,因为ArrayList是有序的,所以第一个被使用的连接肯定是使用时长最长的连接,获取这个最长的连接,判断使用时长是否超长,如果超长那么回滚这个连接的事务,再重新创建一个新的连接并将真实连接对象传递到新对象中,
// Cannot create new connection
//获取使用中的连接,第一个,被使用的最久的那个连接
PooledConnection oldestActiveConnection = state.activeConnections.get(0);
如果第一个没超时,那么当前线程进行等待(wait),默认等待时长是20秒,
// Must wait
//如果第一个连接没有超时,那么进行等待
try {
if (!countedWait) {
//等待数+1
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
state.wait(poolTimeToWait);
//计算等待时间
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
4.3.3 经过上面2步获取到连接之后,再检测连接是否可用,如果不可用
总的坏连接数 > 最大空闲连接数 + 最大坏连接数, 则判定这个数据源有问题,不能获取正常的连接
if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
4.4 pingConnection 检测连接是否可用
4.4.1 先校验真实连接是否关闭
4.4.2 判断校验的开关是否打开
4.4.3 执行测试的SQL语句
Connection realConn = conn.getRealConnection();
//try -resouce语法,出现异常statement会自动关闭
try (Statement statement = realConn.createStatement()) {
//链式编程
statement.executeQuery(poolPingQuery).close();
}
if (!realConn.getAutoCommit()) {
//如果没开开启自动事务,那么回滚上一个查询语句,避免造成影响
realConn.rollback();
}
5.PoolState 封装数据源的容器
这个对象内封装了正常使用的连接和空闲连接的数组,并记载了一些数据源被使用过程中的数据
转载地址:http://crnvi.baihongyu.com/