关于 C3P0 连接池的一种误解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Henzox/article/details/61428131
背景

做过 Java 后端的一定用过 C3P0 连接池,它极易使用,简单配置即可以让我们的应用拥有了一个功能强大的数据库连接池,但对于从连接池里面获取的连接是否需要调用 close 方法释放,坊间众说纷纭。认为不需要释放的认为,连接池已经做好了处理,close 只是归还连接到连接池,并不是真的释放,到底哪一种说法对,大家都拿出了测试代码去验证,但始终没有定论,个人认为答案就在代码中,为何不一探究竟。

前提

因为项目中用到了 C3P0-0.9.2.1.jar 我就研究了一下它的代码实现。代码量不小,并且各种设计模式夹杂其中,底层使用了对象池去管理连接对象。主要流程如下(不是标准的流程图,但比较形象)。
这里写图片描述

简单说明

涉及到的主要的类都已经在图中列出来了。简单来讲(下面的说明省去了框架中使用的一些接口,直接使用具体类来说明),连接池肯定需要有人把连接放进去,然后有使用者去循环使用这些连接。资源池是有 BasicResourcePool 来管理,它是回调 C3P0PooledConnectionPool 的内部类 PooledConnectionResourcePoolManager 来添加资源对象的,而 PooledConnectionResourcePoolManager 是通过 WrapperConnectionPoolDataSource 来创建连接,封装成连接对象添加进资源池的。真正的数据库 JDBC 连接,这里称为物理连接是由 DriverManagerDataSource 去建立的。那么问题就变得简单了,我们看一下,往资源池里放的是什么连接对象就知道连接池里面管理的连接对象的具体类型了。在 WrapperConnectionPoolDataSource->getPooledConnection 中我们可以明显的看到, new NewPooledConnection() 这个对象放进去的资源对象池。它是个什么呢,看一下实现发现,它里面包含了一个 NewProxyConnection,用户最终会得到一个这样的连接对象。它其实是一个对 C3P0PooledConnection 的静态代理对象,用户得到的连接,都是基于它的接口。很显然,它封装了 close 方法,close 方法的具体实现就是,markClosedProxyConnection,去归还进连接池。

总结

所以从 C3P0 连接池是获得的连接其实是需要关闭的,至少对我这个版本是这么实现的。谣言止于代码,外在的测试情况有时候能帮助我们得到一些结论,但真实的情况往往看代码来的更直接。
C3P0 代码很值得一看,设计比较精巧,读懂它对 Java 编码能力的成长,非常有帮助。

展开阅读全文

没有更多推荐了,返回首页