双亲委派机制SPI

news2024/11/18 17:39:36

SPI如何破坏双亲委派机制?可根据以下概念一步步深入

什么是双亲委派机制?

双亲委派机制是Java类加载器体系中采用的一种类加载策略,旨在保证类加载的安全性和稳定性。

这一机制规定了类加载的顺序和规则,即当一个类加载器收到类加载请求时,首先不会自己去尝试加载这个类,而是将这个任务委托给它的父类加载器去完成,只有当父加载器无法加载该类时(表现为抛出ClassNotFoundException),才会尝试自己加载。

 

优点:核心的包,谁也改变不了,保证了安全性。

缺点:在于它的隔离性,Bootstrap加载器无法去加载应用程序的类。(后面就引出SPI的概念)

1 先去自定义加载器加载,自定义加载器没有加载过这个类,委派给应用类加载器

2 应用类加载器也没有加载过这个类,委托给扩展类加载器

3 扩展类加载器没有加载过这个类,委托给根加载器,根加载器去rt.jar的包里去找需要加载的类,rt.jar包里没有,就让扩展类加载器去ext路径下去找

4 扩展类加载器也没有找到,就让应用类加载器去CLASSPATH下面找…

举例验证:当你自定义一个java.lang.String的类,去new这个对象时,加载的仍然是Java自带的String对象,而不是你自定义的String对象。(详细如下图)

什么是SPI?

SPI全称ServiceProviderInterface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。SPI的作用就是为这些被扩展的API寻找服务实现。

SPI使用方式?

1 定义一个接口,并创建它的实现类

2 然后在项目的src/main/resource/META-INF/services目录下创建一个与上述接口的全限定名一致的文件,在这个文件中写入接口的实现类的全限定名

3 运行时,会查找加载这些实现类。(比如下面举例的加载mysql驱动程序)

为什么你在自己的JDBC项目中没有找到META-INF/services/java.sql.Driver文件?

如果你的项目是直接使用像Spring Boot这样的现代框架,它们通常有自动配置或者依赖管理特性,能自动处理JDBC驱动的加载,而不需要你手动放置这个文件。特别是当你通过Maven或Gradle等构建工具管理依赖时,驱动的SPI配置已经是驱动包内部的事情,你的项目不需要直接包含这个文件。

什么是rt.jar?

rt.jar 是 Java Runtime Environment (JRE) 的一个核心组件,全称为 Runtime JAR

如何“破坏”?

SPI核心类在rt.jar 位于Bootstrap ClassLoader启动类加载器中,但是SPI需要实现来自不同厂商提供的数据库Driver实现类,而这些来自不同厂商的SPI接口实现类(如com.mysql.cj.jdbc.Driver)位于Application ClassLoader应用类加载器中

为何说“破坏”?

尽管SPI本身是由启动类加载器加载,但是它间接的通过应用类加载器加载第三方驱动类,绕过了严格的双亲委派机制

为什么要破坏?

因为使用双亲委派有一定的局限性,在正常情况下,用户代码一定是依赖核心类库的,所以双亲委派加载机制是没有问题的,但是在加载核心类库时,又要反过来使用用户代码,双亲委派就无法满足。这是什么样的一个场景呢?比如jdbc利用Driver.Manager.getConnection获取连接时,DriverManager是由根类加载器Bootstrap ClassLoader加载的,在加载DriverManager时,会执行其静态方法,加载驱动程序(也就是Driver接口的实现类),这些实现类都是由第三方数据库厂商提供,根据双亲委派原则,第三方类不可能被根类加载器加载

双亲委派机制源码解析?

这里forName进行加载类,forName方法的getClassLoader是获取caller对应的ClassLoader,caller就是指当前调用的forName方法的那个类,即ReflectionTest这个类,因为这个类是自己写的,所以在CLASSPATH路径下,获取到的加载器应该是应用类加载器(App ClassLoader),解析去会尝试用应用类加载器加载Persion类

通过findLoadedClass(name),去判断当前类加载器有没有加载过,没有加载过,并且parent加载器不为空,就调用parent加载器的loadClass方法…(由此递归)

当到根加载器调用loadClass方法的时候,由于根加载器没有parent,所以就执行findBootstrapClassOrNull(name)去尝试加载类,如果加载不到再让子类去加载

SPI破坏双亲委派机制- JDBC应用场景源码解析?

补充说明:Class.forName("com.ibm.db2.jcc.DB2Driver");这种写法源码里是获取的应用类加载器,这里没有问题,正常的做法。

          但是java1.6开始,后期的SPI版本是不需要写这句代码的,即不需要显示的指定驱动程序,DriverManager会自动查找合适的驱动,从而引出SPI为什么会破坏双亲委派机制。

1 假设这里按照双亲委派的加载思想,这里ServiceLoader是属于rt包,属于根加载器,根加载器去加载mysql的驱动,肯定是找不到的,而且你也没有向下去委托扩展类加载器的路,因为你起步就是根加载器,没法往下递归了,根加载器加载不到,就结束了

2 但是,SPI这里并没有这样去做,而是从Thread.currentThread().getContextClassLoader()获取类加载器,这里获取到的是应用类加载器(为什么获取到应用类加载器?下面进行了详细解释),然后由应用类加载器完成加载

 

ClassLoader构造函数

获取系统的classLoader

初始化classLoader,从Launcher中获取ClassLoader

Launcher是干嘛的?Launcher是一个启动类,Lanucher创建了扩展类加载器,创建了应用类加载器,并把扩展类加载器添加成父类,并且把应用类加载器添加到当前线程的ContextClassLoader 即Thread.currentThread().SetContextClassLoader()

但是,上图中并没有创建bootstrap加载器,为什么呢?因为bootstarp加载器是jvm内部创建,默认是所有机载器的父类。

总结:

1 SPI加载方式实际上是通过获取当前线程的应用类加载器加载的rt包的接口实现类,这些实现类是存在于CLASSPATH中

2 而双亲委派机制,是根据你当前调用forName的那类,来决定起点加载器是哪一个,再向上委派,向下加载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2162217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决启动docker desktop报The network name cannot be found的问题

现象 deploying WSL2 distributions ensuring main distro is deployed: checking if main distro is up to date: checking main distro bootstrap version: getting main distro bootstrap version: open \wsl$\docker-desktop\etc\wsl_bootstrap_version: The network name…

基于Springboot+vue实现的Cosplay论坛系统

基于springbootvue实现的Cosplay论坛系统 (源码L文ppt)4-066 2.3 系统功能分析 Cosplay论坛系统中采用了Java的springboot框架进行开发,在数据库上选择MYSQL,在功能上Cosplay论坛系统我划分为了普通用户管理模…

Proteus如何添加数码管

1、打开安装好的Proteus,点击上方菜单栏中的“库”,再选择“从库选取零件”,或者在左侧元件列表中单击鼠标右键,再点击右键菜单中的“从库中挑选”选项。 2、之后在元器件库中,点击类别中的“Optoelectronics”&#…

破解 oklink 网站加密数据(升级版)

大家好!我是炒青椒不放辣,关注我,收看每期的编程干货。 逆向是爬虫工程师进阶必备技能,当我们遇到一个问题时可能会有多种解决途径,而如何做出最高效的抉择又需要经验的积累。本期文章将以实战的方式,带你详细地分析并破解 oklink 网站加密数据 特别声明:本篇文章仅供学…

python脚本程序怎么写更优雅?argparse模块巧妙应用

前言 命令行程序,也称CLI程序,另一个直观的名字是脚本程序,简称脚本,由于没有图形用户界面(GUI),所以脚本程序常见的交互方式有3种: 1、脚本程序中读取环境变量,比如env…

解决小爱音箱连接Windows10蓝牙时,语音控制会中断音乐播放的问题

解决天猫精灵连接Windows10蓝牙时,语音控制会中断音乐播放的问题 解决小爱音箱连接Windows10蓝牙时,浏览器控制音量会中断音乐播放的问题 用小爱音箱当蓝牙音响的时候,遇到个很困扰的问题,每次小爱音箱语音控制的过程中,都会启动…

3.js - 运动曲线

这个球,绕着这个红色的线圈转 代码 import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControlslet scene,camera,renderer,controls nulllet moon,earth null// 根据,一系列的点,创建曲线 le…

活动报名丨智源Workshop,从o1出发探索LLM推理与思维链

近期o1模型的发布,预示着AI在处理高度复杂问题上再次迈出一大步。大规模强化学习算法在一个数据极高的训练过程中,教会了模型如何利用其思维链进行富有成效的思考。 北京时间9月19日(本周四)晚7点,智源社区将组织「智源…

响应式布局-媒体查询父级布局容器

1.响应式布局容器 父局作为布局容器,配合自己元素实现变化效果,原理:在不通过屏幕下面吗,通过媒体查询来改变子元素的排列方式和大小,从而实现不同尺寸屏幕下看到不同的效果。 2.响应尺寸布局容器常见宽度划分 手机-…

Vue 中 watch 的使用方法及注意事项

前言 Vue 的 Watch 是一个非常有用的功能,它能够监听 Vue 实例数据的变化并执行相应的操作。本篇文章将详细介绍 Vue Watch 的使用方法和注意事项,让你能够充分利用 Watch 来解决 Vue 开发中的各种问题。 1. Watch 是什么? 1.1 Watch 的作…

[js逆向学习] fastmoss电商网站——店铺排名

逆向目标 网站:https://www.fastmoss.com/shop-marketing/tiktok接口:https://www.fastmoss.com/api/shop/shopList/参数:fm-sign 逆向分析 我们今天要分析的是店铺排名,先分析网络请求,找到目标接口 按照上图操作…

Redis: 特点,优势,与其他产品的区别以及高并发原理

入门Redis概述 1 )选择Redis是因为其高性能 因为 Redis 它数据存储的机制是存在内存中的,减少了传统关系数据库的磁盘IO它是单线程的保证了原子性,它还提供了事务,锁等相关的机制 2 )Redis 环境安装配置 linux 或 d…

STM32 map 文件浅析

目录 一、概述二、Section Cross References三、Removing Unused input sections from the image四、Memory Map of the image1、Local Symbols2、全局符号(Global Symbols) 五、Image Symbol Table六、Image component sizes 一、概述 .map 文件是编译…

Shader Graph Create Node---Input

四、Input 1、Basic 一些基础的变量节点 2、Geometry 1)、Bitangent Vector(双切线向量) 通常与顶点位置、法线向量和切线向量一起使用。 法线向量(Normal Vector):垂直于表面的向量。 切线向量(Tangent Vector)…

Vue3项目开发——新闻发布管理系统(八)

文章目录 十、新闻管理模块设计开发1、新闻管理主页面设计1.1 基本架构搭建1.1.1 搜索表单1.1.2 新闻主表格样式(静态数据模拟渲染)1.2 新闻分类选择框1.2.1 新建组件1.2.2 页面中导入渲染1.2.3 调用接口,动态渲染下拉分类,设计成 v-model 的使用方式1.2.4 父组件定义参数绑定…

共建智能座舱AI应用生态 夸克合作斑马智行开拓AI搜索新场景

近日,在2024云栖大会上,夸克与斑马智行达成合作,将面向汽车座舱场景,为用户打造专属AI新体验。夸克以AI搜索为中心的一站式AI服务融入座舱数字化生态,进一步拓展使用场景和能力边界。 9月20日,斑马智行发布…

【Geoserver使用】REST API调用(工作空间部分)

文章目录 前言一、Geoserver REST API(GeoServer Workspace)二、GeoServer Workspace接口使用1.GET请求 /workspaces2.POST请求 /workspaces3.GET请求 /workspaces/{workspaceName}4.PUT /workspaces/{workspaceName}5.DELETE /workspaces/{workspaceName} 总结 前言 根据Geos…

【Day20240924】联邦学习中的方法 改进

文章目录 前言一、FedAvg二、FedProx三、MOON四、FedDyn五、FedAsync六、PORT七、ASO-Fed八、FedBuff九、FedSA 前言 几种异步的方法: FedAsync PORT ASO-Fed FedBuff FedSA 几种同步的方法: FedAvg FedProx MOON FedDyn 一、FedAvg FedAvg基本步骤&a…

MySQL 中存储过程参数的设置与使用

《MySQL 中存储过程参数的设置与使用》 在 MySQL 数据库中,存储过程是一组预先编译好的 SQL 语句集合,可以接受参数并返回结果。使用存储过程可以提高数据库的性能和可维护性,同时也可以减少网络流量和代码重复。那么,如何在 MyS…

UEFI EDK2框架学习 (一)

01 Shell界面打印 执行qemu指令后 qemu-system-x86_64 -drive ifpflash,formatraw,fileOVMF.fd -nographic -net none出现shell界面 02 在UEFI shell中创建APP 创建SimplestApp文件夹以及SimplestApp.c、SimplestApp.inf cd edk2 mkdir SimplestAppuuidgen // generate …