目录
SPI 是什么
SPI 的全称叫做:Service Provider Interface,它是一种通过外界配置来加载具体代码内容的技术手段。主要用来解耦。
直译过来是服务提供者接口,学名为服务发现机制,它通过在ClassPath路径下的META-lNF/services文件夹中查找文件,并自动加载文件里所定义的类。
SPI技术是当前各款中间件都在主流使用的一项扩展技术,其中比较具有代表性的RPC框架Dubbo内部的核心思想就是采用SPI这种扩展技术来实现可插拔式组件的,包括Springboot的factories、数据库驱动的加载。
举个例子来说,假如有一个框架有一个接口,他有自己默认的实现类,但是在代码运行的过程中,你不想用他的实现类或者想扩展一下他的实现类的功能,但是此时你又不能修改别人的源码,那么此时该怎么办?
这时spi机制就有了用武之地。一般框架的作者在设计这种接口的时候不会直接去new这个接口的实现类,而是在Classpath路径底下将这个接口的实现类按作者约定的格式写在一个配置文件上,然后在运行的过程中通过java提供的api,从所有jar包中读取所有的这个指定文件中的内容,获取到实现类,用这个实现类,这样,如果你想自己替换原有的框架的实现,你就可以按照作者规定的方式配置实现,这样就能使用你自己写的实现类了。
Java的SPI机制的缺点
1.在META-INF/service下的配置中如果存在N个实现类,采用JDK自带的SPI机制会一次性
将它们进行初始化加载。在加载的过程中如果涉及到了一些较耗时的操作,会非常浪费
资源。
2.如果扩展点加载失败,会导致调用方报错,而目这个错误很难定位到是这个原因。
所以为了优化这些存在的问题,后期许多中间件技术都使用了自研的SPI机制,例如Dubbo、
SpringBoot。
实际使用
比如在 properties 中 配置相关的内容,比如
serverSerialize=kryo
以及配置 代理层的实现 路由算法 注册中心的类型 序列化框架等等,期望在程序中能够按照我们的配置去运行。
一种方法是不断的判断,if 读到的参数是A ,创建a实例 else if 读到的参数是B,创建b实例,或者 switch case, 写死在程序中。
但是这样写的代码可扩展性很差,可以使用SPI,用一个 map,键是不同的接口全类名,值是一个 map,map 里面保存了不同的实现类以及对应的实例全类名,到时候根据接口的参数去map中取到对应的全类名,并进行实例的创建。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92780.html