在上一次【https://www.cnblogs.com/webor2006/p/9260949.html】已经对ServiceLoader这个类的javadoc通读了一遍,这次来分析一下它是如何来加载驱动的底层细节,先来回顾一下上一次编写的程序:
然后重点是看第一句加载的代码:
那跟进去看一下呗,在看细节之前先来读一下它的javadoc:
而看一下它的实现:
首先获取的是当前线程上下文类加载器,然后再去调用它的带有两个参数的重载方法,在继续往下跟进之前先来挼一下获取线程上下文类加载器的一个意图,先来看一下MyTest25具体是由系统类加载器加载:
所以此时ServiceLoader也肯定是先由系统类去加载,而根据双亲委托最终会委托给根类加载器去加载,好!此时再到load()方法里面,默认当然也是由根类加载器去加载驱动喽,但是很明显具体的驱动都是放在classpath当中很明显是没法由根类加载器加载的,所以这里获取线程上下文类加载器,而默认它就是系统类加载器嘛,所以改变了委托的策略,最终具体驱动就可以用系统类去加载的,这也是线程上下文类加载器的使用场景之所在,继续往下分析:
接着调用reload()方法了:
也就是这个ServiceLoader.load()方法就是初始化了一个延迟迭待的对象,好再看下一句应用代码:
先来简单看一下javadoc对它的描述:
再看一下它的具体实现:
好又回到我们应用的代码往下走:
判断迭待器有没有下一个,此时底层就会:
此时的细节就一览无余啦,看:
其中的PREFIX之前也看到过,如下:
如果有下一个,接下来就进行取值了,如下:
至此整个SPI的加载过程就分析完了,其最最核心的东东就是这个线程上下文类加载器的代码,如下:
如果没有它是不可能正常的能加载到具体的驱动类的,这又进一步又看到线程上下文类加载器的重要性!!
好,接下来做实验咱们来改一改线程类上下文类加载器,看下效果:
再來修改:
运行看结果:
是不是通过这个修改已经完完全全对线程上下文的类加载器的重要性彻底的搞清楚了。
为了进一步理解,此时将JVM的“-XX:+TraceClassLoading”用来观察类的加载情况的参数给加上:
运行,先将设置的上下文给去掉: