上面代码首先将连接从活跃连接集合中移除,然后再根据空闲集合是否有空闲空间进行后续处理。如果空闲集合未满,此时复用原连接的字段信息创建新的连接,并将其放入空闲集合中即可。若空闲集合已满,此时无需回收连接,直接关闭即可。pushConnection 方法的逻辑并不复杂,就不多说了。
我们知道获取连接的方法 popConnection 是由 getConnection 方法调用的,那回收连接的方法 pushConnection 是由谁调用的呢?答案是 PooledConnection 中的代理逻辑。相关代码如下:
// -☆- PooledConnection public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); // 检测 close 方法是否被调用,若被调用则拦截之 if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) { // 将回收连接中,而不是直接将连接关闭 dataSource.pushConnection(this); return null; } else { try { if (!Object.class.equals(method.getDeclaringClass())) { checkConnection(); } // 调用真实连接的目标方法 return method.invoke(realConnection, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } }在上一节中,getConnection 方法返回的是 Connection 代理对象,不知道大家有没有注意到。代理对象中的方法被调用时,会被上面的代理逻辑所拦截。如果代理对象的 close 方法被调用,MyBatis 并不会直接调用真实连接的 close 方法关闭连接,而是调用 pushConnection 方法回收连接。同时会唤醒处于睡眠中的线程,使其恢复运行。整个过程并不复杂,就不多说了。
4.4 小节本章分析了 PooledDataSource 的部分源码及一些辅助类的源码,除此之外,PooledDataSource 中还有部分源码没有分析,大家若有兴趣,可自行分析。好了,关于 PooledDataSource 的分析就先到这。
5.总结本篇文章对 MyBatis 两种内置数据源进行了较为详细的分析,总的来说,这两种数据源的源码都不是很难理解。大家在阅读源码的过程中,首先应搞懂源码的主要逻辑,然后再去分析一些边边角角的逻辑。不要一开始就陷入各种细节中,容易迷失方向。
好了,到此本文就结束了。若文章有错误不妥之处,希望大家指明。最后,感谢大家阅读我的文章。
附录:MyBatis 源码分析系列文章列表 更新时间 标题2018-07-16 MyBatis 源码分析系列文章导读
2018-07-20 MyBatis 源码分析 - 配置文件解析过程
2018-07-30 MyBatis 源码分析 - 映射文件解析过程
2018-08-17 MyBatis 源码分析 - SQL 的执行过程
2018-08-19 MyBatis 源码分析 - 内置数据源
本文在知识共享许可协议 4.0 下发布,转载需在明显位置处注明出处
作者:田小波
本文同步发布在我的个人博客:
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。