博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么说java spi破坏双亲委派模型?
阅读量:6409 次
发布时间:2019-06-23

本文共 2281 字,大约阅读时间需要 7 分钟。

虽然有SPI破坏双亲委派模型的说法,但我不太认同。简单说下。

双亲委派模型(再次吐槽下这个翻译),是一种加载类的约定。这个约定的一个用处是保证安全。比如说你写Java用了String类,你怎么保证你用的那个String类就是JDK里提供的那个String类呢?答案是对于JDK基础类,JDK要用特殊的ClassLoader来保证在正确的位置加载。JDK主要有3个自带ClassLoader:

•最基础:Bootstrap ClassLoader(加载JDK的/lib目录下的类)次基础:Extension

•ClassLoader(加载JDK的/lib/ext目录下的类)

•普通:Application ClassLoader(程序自己classpath下的类)

双亲委派模型要求如果一个类可以被委派最基础的ClassLoader加载,就不能让高层的ClassLoader加载。这样你就知道你用的String类一定是被BootstrapClasserLoader加载的/lib下的那个rt.jar的那个java/lang/String.class.

但这个模型不是强制的。如果你自己写个自己的ClassLoader,你可以不理会它。比如你可以写个自己的ClassLoader去自己规定的一个神怪的目录里加载自己写的String.class。当然Java Runtime能够识别出这俩String不是一个类,哪怕他们的Full Qualified Class Name一模一样。所以如果你这做了,大概率是自作自受。当如果你真的知道自己在干啥,是能够玩出一些花的。

顺便说一句,这个机制的安全性是有限的。假如有人能登入服务器,能够直接替换JDK目录的文件。上述机制也就失效了。为了保证严格的安全,还应该保证系统文件要做数字签名。

另外一点是,这个模式虽然“安全“,但是损失了一丢丢灵活性。就比如java.sql.Driver这个东西。JDK只能提供一个规范接口,而不能提供实现。提供实现的是实际的数据库提供商。提供商的库总不能放JDK目录里吧。

ava从1.6搞出了SPI就是为了优雅的解决这类问题——JDK提供接口,供应商提供服务。编程人员编码时面向接口编程,然后JDK能够自动找到合适的实现,岂不是很爽?

但是便利的同时也带来了困扰。提供商提供的类不能放JDK里的lib目录下,所以也就没法用BootstrapClassLoader加载了。所以当你代码写了

Class clz = Class.forName("java.sql.Driver"); Driver d = (Driver)clz.newInstance();

时,这个代码会用Bootstrap ClassLoader尝试去加载.问题是java.sql.Driver是个接口,无法真的实例化,就报错了。

没有SPI时,你可以现在classpath里加一个mysql-connector-java.jar,然后这样写

Class clz = Class.forName("com.mysql.jdbc.Driver"); Driver d = (Driver) clz.newInstance();

这就没问题了,这里用了Application Classloader加载了mysql-connector-java.jar的com.mysql.jdbc.Driver。问题是你hard code了一定要加载"com.mysql.jdbc.Driver",不是很优雅,不能实现“用接口编程,自动实例化真的实现“的这种编码形式。

使用SPI后,代码大致会这样

Connection connection = DriverManager.getConnection("jdbc:mysql://xxxxxx/xxx", "xxxx", "xxxxx");

DriverManager就根据"jdbc:mysql"这个提示去找具体实现去了。

然后

System.out.println(connection.getClass().getClassLoader());

就会看到这里的结果是Application ClassLoader。这就好像Application ClassLoader加载了本来应该由BootstrapClassLoader加载的java.sql.Connection一样。看起来像是违反了双亲委派模型。但实际上,这里的Connection的类型实际上是“com.mysql.jdbc.JDBC4Connection“,也是个第三方类。AppClassLoader加载一个第三方类看起来并没有违反模型。

再进一步调查下Connection接口自己的加载情况:

System.out.println(java.sql.Connection.class.getClassLoader());

会发现返回的null。说明Connection自己是被Bootstrap ClassLoader加载的。

综上,并没有说Bootstrap ClassLoader加载了个第三方库或者Application ClassLoader加载了JDK的库的情况发生。

所以能否请题主给出具体哪里写了“SPI破坏双亲委派模型“?我再仔细看看是不是前后哪里谁理解错了。可能是我错了,也可能是那个参考错了。

转载于:https://juejin.im/post/5d01f547518825664b6cdc73

你可能感兴趣的文章
centos7.x搭建svn server
查看>>
Oracle数据库中查看所有表和字段以及表注释.字段注释
查看>>
原码编译安装openssh6.7p1
查看>>
tuxedo install and configure in as4 u5
查看>>
防火墙基础知识
查看>>
项目实战:自定义监控项--监控CPU信息
查看>>
mysql DATE_FORMAT(date, format) 函数
查看>>
easyui-datetimebox设置默认时分秒00:00:00
查看>>
蚂蚁分类信息系统5.8多城市UTF8开源优化版
查看>>
Linux学习笔记序列文章——概述
查看>>
构建高可用服务器之五 Keepalive冗余LVS
查看>>
在django1.2+python2.7环境中使用send_mail发送邮件
查看>>
“Metro”,移动设备视觉语言的新新人类
查看>>
PHP源代码下载(本代码供初学者使用)
查看>>
Disruptor-NET和内存栅栏
查看>>
Windows平台ipod touch/iphone等共享笔记本无线上网设置大全
查看>>
播放加密DVD
查看>>
分享Silverlight新鲜事 - Silverlight Firestarter全球会议
查看>>
产品设计体会(3013)项目的“敏捷沟通”实践
查看>>
RHEL6.3基本网络配置(1)ifconfig命令
查看>>