标签:The logging 程序 int 自动类型转换 区别 inter ima gui
SPI是Service Provider Interface的简称,是JDK默认提供的一种将接口和实现类进行分离的机制。这种机制能将接口和实现进行解耦,大大提升系统的可扩展性。
SPI机制约定:当一个Jar包需要提供一个接口的实现类时,这个Jar包需要在META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该Jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
比如下面的列子,jcl-over-slf4j
这个Jar包提供了conmon-logging中LogFactory
这个接口的实现。
文件中的内容如下:
# 这里表名具体的实现类是`org.apache.commons.logging.impl.SLF4JLogFactory`这个类
org.apache.commons.logging.impl.SLF4JLogFactory
# Axis gets at JCL through its own mechanism as defined by Commons Discovery, which
# in turn follows the instructions found at:
# http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider
JDK为了方便查找服务的实现,还提供了一个工具类:java.util.ServiceLoader。
ServiceLoader<Object> loader = ServiceLoader.load(LogFactory);
loader.forEach((item)->{
System.out.println(item);
});
上面代码中使用ServiceLoader
遍历使用SPI机制提供的所有LogFactory
实现。
SPI机制的主要应用有框架扩展和组件的替换等,比如
下面就一步步从定义接口到提供SPI实现类来演示下SPI机制具体的使用方式。
step1:先定义一个接口
public interface SaySomething {
String say(String name);
}
step2:编写实现类
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机制
public static void main(String[] args) {
ServiceLoader<SaySomething> loader = ServiceLoader.load(SaySomething.class);
loader.forEach(item ->{item.say("csx");});
}
在开发中我们还经常会提到API这个名词,下面也总结下两者的区别:
API (Application Programming Interface)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。
SPI (Service Provider Interface)是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现。 从使用人员上来说,SPI 被框架扩展人员使用。
优点
缺点
ServiceLoader
并不是线程安全的。标签:The logging 程序 int 自动类型转换 区别 inter ima gui
原文地址:https://www.cnblogs.com/54chensongxia/p/12372027.html