前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >美团到店一面,SPI 机制了解过么?最重要的部分是什么?

美团到店一面,SPI 机制了解过么?最重要的部分是什么?

作者头像
飞天小牛肉
发布2024-05-22 20:05:52
870
发布2024-05-22 20:05:52
举报
文章被收录于专栏:飞天小牛肉飞天小牛肉

什么是 SPI

SPI 全称为 (Service Provider Interface) ,是 JDK 内置的一种服务提供发现机制,为使用者提供了服务扩展点,使用者无需修改源码就可以自定义服务实现,简单理解就是为服务的具体实现提供了一个可插拔机制。

比如你的项目中

SPI 的Java doc 如下,感兴趣的小伙伴可以阅读下:

A service is a well-known set of interfaces and (usually abstract) classes. A service provider is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself. Service providers can be installed in an implementation of the Java platform in the form of extensions, that is, jar files placed into any of the usual extension directories. Providers can also be made available by adding them to the application's class path or by some other platform-specific means

Java SPI 实战

设想这样一个场景,你写了一个框架要给别人用,你内置了一些序列化的方法,但是总有些使用者会有自己的特殊的序列化逻辑,这时候你就可以把序列化方法的接口通过 SPI 暴露出去,交给使用者来自定义实现。这样,使用者就可以接入自己自定义的序列化方法。

如下,我们定义一个序列化接口:

重点在这里的 load 方法,我们通过 ServiceLoader.load() 来加载指定的 Serializer 实现类列表,然后使用第一个实现类。具体底层原理咱们先按下不表。

再随便写两个实现类实现这个接口:

再建立一个以暴露出去的接口的全路径为命名的文件,比如我这里的就是 com.example.draft.Serializer,注意这个文件一定要放在 resources/META-INF/services 下面

文件的内容也很简单,就是你想使用的 Serializer 接口具体实现类的全路径,多个实现类之间直接换行就可以,比如:

至此,SPI 机制全部完成,我们来测试下:

我们通过 load 方法加载了配置文件中配置的第一个实现类(也就是 SerializerImpl2),并调用了它的 serialize 方法,输出的内容是:

以上,是单体项目的示范,你可以把这个项目打成 jar 包,别人导入这个 jar 包的时候,同样通过上述配置文件的方法,来自定义暴露出来的 SPI 接口。

Java SPI 原理

不难理解,SPI 的重点就是 ServiceLoader,看源码,我们发现这个类是一个 final 类型的,所以是不可被继承修改,同时它实现了 Iterable 接口,方便后续我们能够通过迭代的方式得到对应的服务实现。

再往下,可以看到一个熟悉的常量定义 META-INF/services/

重点看 load 方法:

简单来说,load 的核心逻辑就是使用指定的类型和当前线程绑定的类加载器(ClassLoader)实例化了一个 LazyIterator 对象,并清除 Provider 缓存。

ServiceLoader 实现了 Iterable 接口的方法后,具有了迭代的能力,在 iterator() 方法被调用时,首先会在 ServiceLoader 的 Provider 缓存中进行查找,如果缓存中没有命中那么则在 LazyIterator 中进行查找:

在调用 LazyIterator 时,具体实现如下:

没有什么太复杂的逻辑,我这里只截取了关键代码,核心逻辑就 3 点:

  1. 到预先定义的地方(META-INF/service/+类名)去找配置文件
  2. 解析配置文件拿到全类名
  3. 通过反射获取实现类
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 飞天小牛肉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是 SPI
  • Java SPI 实战
  • Java SPI 原理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档