重要参数解读
- maxWait: 获取Connection的最大超时等待时间
- poolingCount:线程池拥有的连接数量
- activeCount: 活跃连接数量
- maxActive: 最大连接池数量
获取连接的流程
- 先进行 init 操作
- 创建DruidConnectionHolder数组
connections
- 根据
initialSize
生成真正的数据库连接,并且加入到connections数组 - 调用
createAndStartCreatorThread()
方法,开启一个创建数据库连接的线程
- 创建DruidConnectionHolder数组
- 调用getConnectionInternal()方法。先从连接池中取出 DruidConnectionHolder,然后再封装成
DruidPooledConnection
对象返回。
重要代码片段
init操作
connections = new DruidConnectionHolder[maxActive]; //定义 数组
DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo); //将PhysicalConnectionInfo封装成DruidConnectionHolder
connections[poolingCount] = holder;//将DruidConnectionHolder放入connections数据组中
生成真正的数据库连接 Connect 并且封装成 PhysicalConnectionInfo
PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
Connection conn;
if (getProxyFilters().size() == 0) {
//最核心代码
conn = getDriver().connect(url, info);
} else {
conn = new FilterChainImpl(this).connection_connect(info);
}
createCount.incrementAndGet();
return conn;
}
用户名和密码如果有回调函数,那么从回调方法中获取 UserName或 Password,如果filters长度不为0,那么执行FilterChain操作。 filters使用这个方式定义:
protected List<Filter> filters = new CopyOnWriteArrayList<Filter>();
getConnectionInternal方法
protected Condition notEmpty;
protected Condition empty;
lock = new ReentrantLock(lockFair);
notEmpty = lock.newCondition();
empty = lock.newCondition();
if (maxWait > 0) {
holder = pollLast(nanos);
} else {
holder = takeLast();
}
DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);// 持有所在线程等
return poolalbeConnection
连接池为空时释放信号操作emptySignal()
protected ScheduledExecutorService createScheduler;
CreateConnectionTask task = new CreateConnectionTask();
createScheduler.submit(task);
//CreateConnectionTask run 使用 lock.lock(); 方法
// 必须存在线程等待,才创建连接
//最后创建连接
physicalConnection = createPhysicalConnection();
recycle原理: 需要回收的连接,检查合格后把连接 holder 加入到 connections 数组中去,达到回收的效果
图解
涉及知识点
- volatile 关键字使用
- FilterChain设计模式
- ReentrantLock、Condition、countDown的使用
- AtomicInteger原子类使用
获得数据源IddataSourceIdSeed
使用
dataSourceIdSeed = new AtomicInteger(0);
dataSourceIdSeed.incrementAndGet();
- CopyOnWriteArrayList 原子List类使用
- ScheduledExecutorService线程池的使用
总结
Druid 数据库连接池使用了不少 JAVA高级操作,这些点都是需要单独去学习的,这样才能更好的掌握Druid。