聊聊SPI机制以及为什么说SPI破坏了双亲委派模型

1、前言

SPI?一开始接触这个概念大部分人都会很懵,SPI是啥?平时就听过API和SCP(狗头),老夫CRUD这么多年了, 还从来没有听说过Java有这么一个玩意。

然而事实是,你虽然没有听过,但你几乎每天都在享受它给你带来的便利。今天我们就来聊聊这个传说中的SPI机制。

2、SPI的概念

SPI(Service Provider Interface),是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用。

听到框架,你是不是心里有一点点印象了呢?

2.1 典型应用:JDBC

最典型的例子就是我们开发中几乎每天都会用到的jdbc。

java.sql.Driver接口由核心类库提供,但是它的实现很明显不是Java提供的,而是各大服务商来提供。

当服务的提供者提供了一种接口的实现之后,需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体的实现类。

JDK中查找服务的实现的工具类是:java.util.ServiceLoader。

那为什么配置文件为什么要放在META-INF/services下面?可以打开ServiceLoader的代码,里面定义了文件的PREFIX如下:

private static final String PREFIX = "META-INF/services/"

而我们在引入的jar里也确实能找到这个东西:

在这里插入图片描述

2.2 SPI机制的通俗理解

到这里可能大家心里对SPI机制已经有了一个大概的了解,实际上它可以理解为一个规范。

举个通俗一点的例子:我有一台手机,需要打电话但是没得卡怎么办?总不可能我做手机的还得负责把你电话卡问题也解决吧?那后面岂不是还有手机壳、耳机等问题?

很明显手机开发商不会给你一条龙服务,它在出厂的时候定义好卡槽大小,不管你是移动还是联通还是电信,只要你根据我的规范设计好电话卡,那我直接放进去手机就能使用。

3、双亲委派模型

在说SPI破坏了双亲委派模型之前,我们先来了解一下什么是双亲委派模型(摘自周志明大神的《深入理解Java虚拟机第三版》):

在这里插入图片描述

3.1 双亲委派模型的好处

在这里插入图片描述

4、为什么说SPI破坏了双亲委派模型

双亲委派模型很好的解决了各个类记载器的基础类统一问题(越基础的类由越上层的类加载器加载)。

基础类之所以称为基础,是因为它们总是作为被用户调用的API,但如果基础类又要回调用户的代码,那该怎么办呢。

4.1 可见性原则

我们都知道,Java的类加载器结构是这样的:


启动类加载器作为应用程序类加载器的上级,启动类加载器加载的类 对应用程序类加载器是可见的。

然而应用程序类加载器加载的类对启动类加载器却是不可见的。

这是由 classloader 加载模型中的可见性(visibility)决定的。可见性原则允许子类加载器查看父ClassLoader加载的所有类,但父类加载器看不到子类加载器的类。

4.2 双亲委派模型的妥协

java.sql.DriverManager通过扫包的方式拿到指定的实现类,完成 DriverManager的初始化。

但是,根据可见性原则,java.sql.DriverManager是启动类加载器负责的,根据双亲委派的可见性原则,启动类加载器加载的 DriverManager 是不可能拿到系统应用类加载器加载的实现类 。

为了解决这个困境,Java的设计团队只好引入了一个不太优雅的设计:线程上下文类加载器 (Thread Context ClassLoader)。

这个类加载器可以通过java.lang.Thread类的setContext-ClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。

通过这个类加载器可以实现功能,但也正是因为如此,双亲委派模型的可见性原则就被破坏了,但这也是无可奈何的事情,所以只能说是妥协~

5、结尾

Java SPI的使用很简单。也做到了基本的加载扩展点的功能。但Java SPI有以下的不足:

  • 需要遍历所有的实现,并实例化,然后我们在循环中才能找到我们需要的实现。
  • 配置文件中只是简单的列出了所有的扩展实现,而没有给他们命名。导致在程序中很难去准确的引用它们。
  • 扩展如果依赖其他的扩展,做不到自动注入和装配
  • 不提供类似于Spring的IOC和AOP功能
  • 扩展很难和其他的框架集成,比如扩展里面依赖了一个Spring bean,原生的Java SPI不支持

这些观点是dubbo官网博客提出的,很明显dubbo的SPI对此做出了改进,至于dubbo具体是怎么做的

传送门在这----->Dubbo可扩展机制实战

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值