经过JDBC驱动加载深入理解线程上下文类加载器机制

关于线程上下文类加载器已经在以前学得比较透了,做为一个收尾,这里用日常J2EE开发时JDBC链接Mysql数据库常见的一段代码经过分析它的底层进一步加深对线程上下文类加载器的理解,因此先来将链接应用代码写上,注意:这里不力求真正的去完成数据的链接,重在在分代码,以下:html

说实话现在的工做重点是搞android的开发,再来看上面的这段代码仍是很是之亲切的,固然啦搞J2EE开发的那就不用多说了,屡见不鲜了,好,接下来先来分析第一行代码:java

对于mysql驱动有两个:mysql

而咱们使用的是第一个,对于forName方法目前咱们也比较清楚它的做用了,看一下它的源码:android

既然会初始化"com.mysql.jdbc.Driver",那就跟到这个类里面,看在初始化的时候干了啥:web

对于类的初始化是位置类加载的第三个阶段,这里再来回忆一下其整个过程:面试

而类的初始化会导至类的static代码【静太代码块,静态变量】获得执行,因此:sql

因此此时会调用DriverManager.registerDriver()方法,可是在调用方法以前确定也得初始化DriverManager嘛,因此跟进去:数据库

是否是如我们分析的这样的呢,我们能够debug看一下,先打上断点:学习

嗯~~彻底正确!继续分析:线程

跟进去:

这是加载JDBC的另一种方式,我们能够打印一下该系统属性:

接着往下执行:

因此最终会用这种方式去加载驱动,因此这个方法就是去执行了驱动的加载工做,流程再回到上一层:

注册驱动里面是如何作的呢?

接着回到主流程的第二句代码:

细心的话能够发现,这句话彻底木有Mysql的API竟然最后就能够生成Mysql的一个链接,这底层是怎么作到的呢?继续跟踪,先简单看一下getConnection的javadoc:

接着看它的具体代码实现:

这里能够打一个段点看一下第三个参数是否如所料:

嗯~~完成正确~~继续往下分析:

继续打断点确认一下是否如预料:

我们debug看一下此时registeredDrivers的值是多少:

呃~~为啥有两个呢,我们第一句代码不仅是指定了一个么,以下:

这是由于现在的mysql版本会自动在这个目录进行寻找并注册驱动:

因此这里须要注意,继续往下:

好,这个细节很是重要,定位到它看一下:

想一想为啥呢?命名空间!!!!可能这块已经都忘得差很少了,由于不一样的类加载器所加载的相同的类是不相等的,如以前【https://www.cnblogs.com/webor2006/p/9157847.html】咱们作实验所示:

回到我们这个场景,因为是SPI的场景,用户能够随意去设置线程上下文类加载器,因此就有可能出现不等的状况,这也是为啥要作一个判断的缘由之所在,继续往下分析:

至此整个JDBC的建立链接的过程就已经分析完了,而类加载器这块的全部知识都已经学完啦,至关之不易,想当初对于类的双亲委托机制只知道概念,每次面试官问到这个时也仅能回到出理论部分,通过这么细致的学习我想无论将来的面试仍是工做当中遇到类加载相关的问题应该是so easy的事啦!

相关文章
相关标签/搜索