spi
实例:
一个接口
一个实现
一个配置
一个main:
源码:
成员
注意这里是Thread Context ClassLoader。
在线程初始化的时候,会取父线程的ClassLoader,全局没有的话 最后会是应用程序类加载器。
获取一个classLoader:
整体看下来好像没有这么神秘,在hasNext中还是用prefix拼了全限定名找到文件,然后用文件流读文件,找出文件中的全限定名,委托给双亲加载
来看一下为什么说jdbc破坏了双亲委派。我们看一下获取jdbc链接的方式:
DriverManager.getConnection();
在加载DriverManager的时候:
可以看到这样一个静态块:
loadInitialDrivers中使用了sericeLoader去加载Driver.class的实现类。DriverManager本身的加载不会有什么问题。只是在DriverManager加载完之后进行初始化的时候,<clinit>执行loadInitialDrivers需要去加载Driver的实现类,但是就很尴尬的发现整个DriverManager是在rt.jar下由启动类加载器负责加载,我一个最顶级超类去加载已经不能 像应用程序类加载器那样双亲委派到到最顶级,加载不行在往下委托给孩子,我自己已经是顶级且委派给我自己,那么我只能加载lib下面的包中的类,但是Driver的实现类被厂商自己实现肯定是在用户类路径中的,我不得不拿到一个应用程序加载器类去帮我做这件事情,于是便有了ServiceLoader的使用
dubbo spi:
总体上使用方法如上。
看下实现源码:
缓存,还用多讲吗?往下看就完事了:
缓存缓存,全是缓存
emm看到这个classLoader大概知道会发生什么了
可以看到按行读取配置之后已经拿到了clazz了。那loadClass做了什么呢
好吧又是缓存。注意这里判断是否是WrapperClass是根据有参的构造方法来的。而普通的扩展点则要求无参的构造方法。
在获得实例之后进行了IOC的注入:
结束,就这些