参考文献:Druid-类图-属性表
本篇为「工具人」文章,建议直接用「ctrl+f」进行查找属性、方法、类名,快速了解其含义和所属类。
1. 类图
主要流程里主要涉及到的类名称、类属性、类方法如下图(淡黄色表示属性,淡蓝色表示方法):

2. DruidAbstractDataSource 抽象类
这个类是 druid 连接池基础类,定义了一些连接池该有的基本属性,以及生成驱动连接对象的方法。
属性表:
| 属性名 | 描述 |
|---|---|
| username | 用户名 |
| password | 密码 |
| jdbcUrl | 驱动连接 |
| driverClass | 驱动class,可以不用配置 |
| initialSize | 初始化连接池**(主流程2)**时需要预先生成的连接对象个数 |
| maxActive | 池内最大连接数,也就是说生成连接的线程在当前池内连接数超过这个指标后就不再工作了,参考主流程3 |
| minIdle | 池内最小闲置连接数,参考流程4.1 |
| maxWait | 在业务线程拿不到可用连接而发生排队时,等待获取到可用连接对象的最大等待时间,参考主流程1和流程1.2 |
| notFullTimeoutRetryCount | 获取不到连接时,会尝试重试,这里表示最大重试次数,参考主流程1 |
| validationQuery | 检测连接有效性时使用的 sql, 一般为 select 1 |
| validationQueryTimeout | 检测超时时间 |
| testOnBorrow | 在取出链接时,是否进行连接可用性测试,默认不开启,参考主流程1 |
| testOnReturn | 在回收连接时,是否进行连接可用性测试,默认不开启,参考主流程5 |
| testWhileIdle | 在闲置时间超出指定时间(timeBetweenEvictionRunsMillis)后进行连接可用性测试 |
| timeBetweenEvictionRunsMillis | 默认60s,一个连接闲置时间超出该值,且设置了testWhileIdle为true时,进行连接可用性测试 |
| inited | 是否已被初始化过,参考主流程2 |
| filters(集合) | 触发责任链执行时需要执行的所有filter |
| maxWaitThreadCount | 默认不开启(-1),表示取不到连接发生等待时阻塞的最大业务线程数,参考流程1.2 |
| keepAliveBetweenTimeMillis | 开启 keepAlive 时,闲置时间超过此会进行检测,检测不会和 testWhileIdle 冲突 |
| minEvictableIdleTimeMillis | 连接的最小闲置时间,小于这个时间的一定不会被杀掉 |
| maxEvictableIdleTimeMillis | 连接最大闲置时间,检测到闲置时间超过此的一定会被杀掉 |
| removeAbandoned | 是否主动回收一些被拿出去使用长久没有归还的连接,默认不开启,参考流程4.2 |
| removeAbandonedTimeoutMillis | 表示在removeAbandoned开启的情况下,触发主动归还的时间间隔。 |
| dbType | 标记该连接池对象是属于什么数据库类型(根据驱动协议头推算出来) |
| validConnectionChecker | druid有多个验证长连接可用性的checker对象,该属性最终会根据数据库类型适配合适的checker对象,参考流程1.3里的init-checker |
| lock | 控制连接池线程安全的全局重入锁(参考全部流程里出现的lock) |
| notEmpty | 由lock创建的Condition,用于连接不够用时阻塞业务线程,同时唤起主流程3的守护线程追加连接,解释参考主流程2的特别说明② |
| empty | 由lock创建的Condition,用于连接足够时(不发生线程等待),阻塞主流程3的守护线程,解释参考主流程2的特别说明② |
| activeConnectionLock | 活动连接重入锁,被借出去的连接称为active连接,这类连接在removeAbandoned开启时会被保存进下面的activeConnections里,利用该锁完成对其操作的安全性,参考主流程1和流程4.2 |
| activeConnections(k-v) | 解释参考上面的描述,参考主流程1和流程4.2 |
| phyMaxUseCount | 最大等待用户数,不建议配置 |
方法表 :
| 方法名 | 描述 |
|---|---|
| testConnectionInternal | 测试连接可用性的基本方法,参考流程1.3 |
| createPhysicalConnection | 新增真正的数据库物理连接,参考流程2.1 |
3. DruidDataSource 类
这个类也是 druid 连接池基础类,扩展了一些其父类的功能,几乎所有的有关连接池管理的操作都在此类完成。
属性表:
| 属性名 | 描述 |
|---|---|
| connectCount | 一共成功从该池获取了多少次连接(只要获取成功一次,就累加一次) |
| recycleCount | 一共成功归还了多少次连接到该池(成功归还一次,累加一次) |
| removeAbandonedCount | 在removeAbandoned开启的情况下,被检查后强制归还的连接数 |
| connections(数组) | 最终池子里没有被使用的闲置连接存放的地方,类型是DruidConnectionHolder |
| poolingCount | pollingCount就是指上面connections的真实数量 |
| activeCount | 当前处于借出状态的连接数(也即是被拿出去使用的连接数),poolingCount+activeCount就是当前该池子里一共有多少个连接,不能超过maxActive,参考主流程3 |
| discardCount | 被丢弃的连接数,触发丢弃的地方有很多,比如流程1.4、流程4.1 |
| evictConnections(数组) | 参考流程4.1 |
| keepAliveConnections(数组) | 参考流程4.1 |
| createConnectionThread(线程) | 生产连接的守护线程,参考主流程3 |
| destroyConnectionThread(线程) | 抛弃连接的守护线程,参考主流程4 |
| logStatsThread(线程) | 打印连接池各项监控指标日志的守护线程,参考主流程2,默认关闭 |
| initedLatch(CountDownLatch) | 倒计数器,用来保证createConnectionThread和destroyConnectionThread两个守护线程全部开启成功。 |
| enable | 连接池对象是否可用,在连接池整体close后,该值为false,表示已关闭的连接池不可用。 |
| keepAlive | 参考流程4.1 |
| loadSpifilterSkip | 是否启用通过SPI机制加载责任链上的filter,默认开启 |
方法表:
| init | 初始化整个连接池,参考主流程2 |
|---|---|
| initFromSPIServiceLoader | 通过SPI机制加载责任链中的filters |
| initValidConnectionChecker | 初始化(适配)检测器,参考流程1.3中的init-checker |
| createAndLogThread | 启动上面表2-1里的logStatsThread线程 |
| createAndStartCreatorThread | 启动上面表2-1里的createConnectionThread线程 |
| createAndStartDestroyThread | 启动上面表2-1里的destroyConnectionThread线程 |
| getConnection | 获取连接方法,参考主流程1 |
| getConnectionDirect | 获取连接方法(通过getConnection触发),参考主流程1 |
| pollLast | 真正从池子里获取连接对象的方法(通过getConnectionDirect触发),参考流程1.2 |
| putLast | 真正归还连接进池子的方法(通过recycle触发),参考主流程5 |
| put | 新增连接对象放进池子里的方法,通过主流程3触发 |
| close | 连接池关闭,不再提供服务,迅速干掉所有连接进入贤者模式。** ** |
| recycle | 连接回收方法,通过下面DruidPooledConnection类的close方法触发,参考主流程5 |
| shrink | 连接池瘦身,参考主流程4、流程4.1 |
| removeAbandoned | 回收长期未回收的连接,默认关闭不检查,通过表1-1里的removeAbandoned属性控制 |
| emptySignal | 触发表1-1里的empty执行signal,用于唤起主流程3新增连接 |
4. DruidConnectionHolder 类
最终存放进池子里的基本类型,该类持有驱动产生的真实 Connection 对象,同时提供一些连接池需要的标记性的属性。
属性表:
| 属性名 | 描述 |
|---|---|
| dataSource(DruidDataSource) | 本身包含一个持有自己实例的连接池对象 |
| conn(Connection) | 真实的驱动连接对象 |
| lastActiveTimeMillis | 上次活动时间,该值在归还连接时会被刷新一次,参考主流程5,除此之外在一句sql 执行结束后,这个值也会被刷新 |
| lastKeepTimeMillis | keepAlive 开启时,上次检测时间,和 keepAliveBetweenTimeMillis 相关 |
| lastValidTimeMillis | 上次活性检测时间,和 timeBetweenEvictionRunsMillis 相关 |
| defaultReadOnly | 是否默认为只读模式,默认不是 |
| defaultAutoCommit | 是否默认开启 AutoCommit,默认开启 |
| discard | 当前连接是否已被抛弃 |
方法表:
| 方法名 | 描述 |
|---|---|
| reset | 在连接对象被归还时,由于使用时可能被业务代码人为的改动一些属性(比如 autoCommit 等)需要把一些属性重新置为默认值,就需要该方法 |
5. DruidPooledConnection类
对外暴露给业务方的连接对象包装类,实际上其内部是包了一层上面的 holder 对象。
属性表:
| 属性名 | 描述 |
|---|---|
| conn(Connection) | 实际的驱动连接对象,通过下面持有的 holder 对象获得并赋值 |
| holder(DruidConnectionHolder) | 持有的 holder 对象 |
| disable | 标记是否可用 |
| ownerThread | 标记最初获取到自己的那个线程(用于决定在 close 时走下方的 close 还是syncClose,参考主流程5) |
| closed | 标记是否已被关闭 |
| running | 标记是否正在运行中,running 被置为 true 的地方,就是执行 excute 方法时。 |
| abandoned | 标记是否已被检查并丢弃,参考流程4.2 |
方法表:
| 方法名 | |
|---|---|
| close | 关闭该连接,将实际连接归还至连接池,参考主流程5 |
| syncClose | 如果是别的线程执行 close 方法,就得启用该方法去做,该方法与上面close的区别就是加了锁控制,参考流程5 |
| recycle | 实际触发 datasource.recycle 方法的方法,参考流程5 |
| 常规操作 | 有 createStatement、commit、rollback 等等常规操作,本篇文章不涉及到,仅做连接池的说明,暂时忽略。 |