重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
SPI是Service Provider Interface的简称,是JDK默认提供的一种将接口和实现类进行分离的机制。这种机制能将接口和实现进行解耦,大大提升系统的可扩展性。
专注于为中小企业提供做网站、成都做网站服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业惠济免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了1000多家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
SPI机制约定:当一个Jar包需要提供一个接口的实现类时,这个Jar包需要在META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该Jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
比如下面的列子,
jcl-over-slf4j
这个Jar包提供了conmon-logging中
LogFactory
这个接口的实现。
文件中的内容如下:
JDK为了方便查找 服务的实现,还提供了一个工具类:java.util.ServiceLoader。
上面代码中使用
ServiceLoader
遍历使用SPI机制提供的所有
LogFactory
实现。
SPI机制的主要应用有框架扩展和组件的替换等,比如
下面就一步步从定义接口到提供SPI实现类来演示下SPI机制具体的使用方式。
step1:先定义一个接口
Copy
`public interface SaySomething {
String say(String name);}`
step2:编写实现类
Copy
public class ASaySomething implements SaySomething { @Override public String say(String name) { return "Hi,"+name+", l am A..."; } }
step3:在resource下添加META-INFO/services目录
添加完这个目录后,添加一个以
SaySomething
接口的全限定名为名字的文件,这个文件的内容是你要设置的具体实现类。这边我们就设置实现类为上面的
ASaySomething
。
step4:使用SPI机制
Copy
public static void main(String[] args) { ServiceLoader
loader = ServiceLoader.load(SaySomething.class); loader.forEach(item ->{item.say("csx");}); }
在开发中我们还经常会提到API这个名词,下面也总结下两者的区别:
API (Application Programming Interface)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。
SPI (Service Provider Interface)是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现。 从使用人员上来说,SPI 被框架扩展人员使用。
优点
缺点
ServiceLoader
并不是线程安全的。