首页 > 其他分享 >SPI与双亲委派模型

SPI与双亲委派模型

时间:2023-03-19 20:33:24浏览次数:30  
标签:委派 java jar Driver class SPI 双亲 ServiceLoader 加载

类加载顺序图:

 

 这样做的好处就是:Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

其次是考虑到安全因素。假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

JDBC为何要破坏双亲委派模型?

在JDBC 4.0后,使用数据库驱动程序,我们不在需要Class.forName来加载驱动程序,只需要把驱动的jar包放到工程的类加载路径中,驱动程序就会自动被加载。这得益于Java中的SPI技术,只需要将加载的类名称放在META-INF/services目录下的java.sql.Driver文件中,即可自动进行加载。在使用上,我们只需下面一行代码就可以创建数据库连接。
Connection con = DriverManager.getConnection(url , username , password ) ;
因为类加载器收到加载范围的限制,在某些情况下父加载器无法加载到需要的文件,就需要委托给子类加载器去加载class文件。 JDBC的Driver接口定义在JDK中,其实现由数据库的各个厂商提供。DriverManager类中要加载各个实现了Driver接口的类统一进行管理,Driver类位于JAVA_HOME中jre/lib/rt.jar中,应该由Bootstrap类加载器进行加载,而各个Driver的实现类位于各个服务商提供的jar包中。根据类加载机制,当被加载的类引用了另外一个类时,虚拟机就会使用装载第一个类(先加载父类)的类加载器装载被引用的类,也就是说应该使用Bootstrap类加载器去加载各个厂商提供的Driver类。但是,Bootstrap类加载器只负责加载JAVA_HOME中jre/lib/rt.jar中所有的class,所以需要由子类加载器去加载Driver的实现类,这就破坏了双亲委派模型。 查看DriverManager类的源码,看到在使用DriverMnager的时候回触发器静态代码块,调用loadInitialDrivers()方法,并调用ServiceLoader.load(Driver.class)加载所有在META-INF/Services/java.sql.Driver文件中的类到JVM内存,完成驱动的自动加载。
static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
}
private static void loadInitialDrivers() {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {

                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator<Driver> driversIterator = loadedDrivers.iterator();

                try{
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                // Do nothing
                }
                return null;
            }
        });
}
子类的类加载器是通过Thread.currentThread().getContextClassLoader()得到的线程上下文加载器。
public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return ServiceLoader.load(service, cl);
}

 

标签:委派,java,jar,Driver,class,SPI,双亲,ServiceLoader,加载
From: https://www.cnblogs.com/zhengbiyu/p/17234162.html

相关文章

  • spi调试相关
    https://zhugeyifan.blog.csdn.net/article/details/117388884?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%......
  • Spider理论系列--协程(一)
    一、协程概念协程又称微线程(纤程),是一种用户态的轻量级线程子程序在所有的语言中都是层级调用的,比如A中调用B,B在执行过程中调用C,C执行完返回,B执行完返回,最后是A执行完毕。......
  • 部署spinnaker
      直接登录官网部署,修改拉取镜像地址可以参考以下文档, https://blog.csdn.net/qq_22917163/article/details/108623113 使用docker运行halyard容器因为采用halya......
  • spingboot-context-path-默认值以及配置
    springboot项目的context-path的默认值:/可以在application.yml配置文件中自行配置:SpringBoot2.0.0.RELEASE版本以及之后server:port:80servlet:context-path:......
  • 某大厂面试题:说一说Java、Spring、Dubbo三者SPI机制的原理和区别
    大家好,我是三友~~今天来跟大家聊一聊Java、Spring、Dubbo三者SPI机制的原理和区别。其实我之前写过一篇类似的文章,但是这篇文章主要是剖析dubbo的SPI机制的源码,中间只是......
  • 可插拔组件设计机制—SPI
    作者:京东物流孔祥东1.SPI是什么?SPI的全称是ServiceProviderInterface,即提供服务接口;是一种服务发现机制,SPI的本质是将接口实现类的全限定名配置在文件中,并由服务......
  • 可插拔组件设计机制—SPI
    作者:京东物流孔祥东1.SPI是什么?SPI的全称是ServiceProviderInterface,即提供服务接口;是一种服务发现机制,SPI的本质是将接口实现类的全限定名配置在文件中,并由服务加载......
  • Robust RFID-Based Respiration Monitoring in Dynamic Environments
    基于RFID的呼吸监测在动态环境中的鲁棒性研究研究内容他们首先分析了移动人员对RFID信号的影响,发现移动人员会造成信号的衰减和多径效应,导致信号质量下降和相位跳变。为......
  • Spinner(列表选项框)的基本使用
    这一节是想给大家介绍一个Gallery(画廊)的一个控件,尽管我们可以不通过兼容使用Gallery,不过想想还是算了,因为Gallery在每次切换图片的时候,都需要重新创建视图,这样无疑会造成......
  • Optimal ANN-SNN conversion for high-accuracy and ultra-low-latency spiking neura
    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布!PublishedasaconferencepaperatICLR2022 ABSTRACT脉冲神经网络(SNN)因其独特的低功耗属性和对神经形......