博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊SPI机制以及为什么说SPI破坏了双亲委派模型
阅读量:2066 次
发布时间:2019-04-29

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

目录

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具体是怎么做的

传送门在这----->

转载地址:http://jmfmf.baihongyu.com/

你可能感兴趣的文章
AJAX 自己研究玩的
查看>>
javascript(js)数组操作
查看>>
用JavaScript脚本实现Web页面信息交互
查看>>
window 窗口对象操作
查看>>
公司一位老员工愤然离去的留信!崩溃!
查看>>
C#技巧:网页表单自动填写技术(以gmail为例)
查看>>
C#基础概念二十五问
查看>>
C#在Excel中将连续多列相同数据项合并
查看>>
C#如何把html中的相对路径变成绝对路径
查看>>
用C#编写发手机中文短信息Windows服务
查看>>
C#的四个基本技巧
查看>>
编程实例 使用C#的BitmapData
查看>>
区分Oracle和SQL Server常用函数调用方法
查看>>
详解Visual C#数据库基本编程
查看>>
第一个C#应用程序
查看>>
第一章C#简介
查看>>
NGWS runtime 技术基础
查看>>
Linux find 文件查询 用法示例
查看>>
Linux 查看文件大小
查看>>
mysql 命令
查看>>