在Java领域,有一种重要的服务扩展机制,即SPI,它在编写框架和项目应用中起着重要的作用。SPI的英文全称为service provider interface,即服务提供接口,在JDK、Spring和Dubbo中都有它的存在。
我个人认为,SPI存在最根本的目的是实现模块或组件的可插拔性,核心思想那便是解耦了。
一、JDK
在JDK的java.util包下有一个非常显眼的类,即ServiceLoader。不妨打开该类的源码,看到注释的第一行是A simple service-provider loading facility,用我粗大的英语能力翻译出大概意思是一个简单的服务提供者加载工具。是的,你没有看错,这就是JDK中SPI机制的核心类。
使用JDK的SPI,需要遵循如下规则:
1、当服务提供方提供接口的具体实现后,在classpath下创建META-INF/services目录。
2、再创建一个以接口全限定名命名的配置文件,将实现类的全类名写入文件。
3、通过ServiceLoader加载模块。
简单示例:
首先定义一个接口
public interface Animal {
void sound();
}
接下来定义两个实现类,分别是Dog和Cat
public class Dog implements Animal {
@Override
public void sound(){
System.out.println("汪汪汪的叫");
}
}
public class Cat implements Animal {
@Override
public void sound(){
System.out.println("喵喵喵的叫");
}
}
然后在classpath下创建META-INF/services目录,创建文件以Animal的全类名命名,比如com.xxx.Animal,文件内写入两个实现类的全类名,如下:
com.xxx.Dog
com.xxx.Cat
最后编写测试代码
public class Test {
public static void main(String[] args) {
ServiceLoader<Animal> serviceLoader = ServiceLoader.load(Animal.class);
serviceLoader.forEach(Animal::sound);
}
}
测试结果如下
"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:C:\Program
汪汪汪的叫
喵喵喵的叫
二、Spring和Dubbo
如果理解了JDK的SPI机制,那么Spring和Dubbo中的SPI也就理解了,原理是一样的,只是实现的方式有些许区别。
Spring中SPI的核心类:
Dubbo中SPI的核心类:
Spring、Dubbo 和JDK SPI实现的区别:
1、配置文件路径不同
2、配置文件内容书写方式不同
3、编码方式不同