打破双亲委派机制有什么用_为什么说SPI打破双亲委派机制

简单介绍ClassLoader的双亲委派机制:

java类通过Classloader加载,Classloader之间有继承关系,AppClassLoader继承ExtClassloader继承BootstrapClassloader。在类加载时,子加载器会调用父加载器来加载类,如果父加载器不能加载类,才会交给子加载器来加载;如果子加载器也加载失败,那么就报异常。

可以看出双亲委派机制是一种至下而上的加载方式,那么SPI是如何打破这种关系?

以JDBC加载驱动为例:

在JDBC4.0之后支持SPI方式加载java.sql.Driver的实现类。SPI实现方式为,通过ServiceLoader.load(Driver.class)方法,去各自实现Driver接口的lib的META-INF/services/java.sql.Driver文件里找到实现类的名字,通过Thread.currentThread().getContextClassLoader()类加载器加载实现类并返回实例。

驱动加载的过程大致如上,那么是在什么地方打破了双亲委派模型呢?

先看下如果不用Thread.currentThread().getContextClassLoader()加载器加载,整个流程会怎么样。

从META-INF/services/java.sql.Driver文件得到实现类名字DriverA

Class.forName("xx.xx.DriverA")来加载实现类

Class.forName()方法默认使用当前类的ClassLoader,JDBC是在DriverManager类里调用Driver的,当前类也就是DriverManager,它的加载器是BootstrapClassLoader。

用BootstrapClassLoader去加载非rt.jar包里的类xx.xx.DriverA,就会找不到

要加载xx.xx.DriverA需要用到AppClassLoader或其他自定义ClassLoader

最终矛盾出现在,要在BootstrapClassLoader加载的类里,调用AppClassLoader去加载实现类

这样就出现了一个问题:如何在父加载器加载的类中,去调用子加载器去加载类?

jdk提供了两种方式,Thread.currentThread().getContextClassLoader()和ClassLoader.getSystemClassLoader()一般都指向AppClassLoader,他们能加载classpath中的类

SPI则用Thread.currentThread().getContextClassLoader()来加载实现类,实现在核心包里的基础类调用用户代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值