配套视频:https://cloud.tencent.com/developer/video/76588
SPI(Service Provider Interface)是一种服务发现机制,它通过在类路径下的META-INF/services目录下的配置文件来发现服务实现类,实现了面向接口编程的扩展性。
Java SPI是JDK自带的一种SPI机制,它通过在META-INF/services目录下的配置文件中指定接口的实现类来实现。Java SPI只能加载到类路径下的实现类,不支持动态添加和删除实现类。Java SPI的实现代码示例如下:
- 定义接口
public interface MyService {
void doSomething();
}
- 实现接口
public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("do something by MyServiceImpl");
}
}
- 配置文件
在META-INF/services目录下创建一个以接口全限定名为文件名的文件,并在文件中指定实现类的全限定名。
代码语言:javascript复制com.example.MyService
com.example.MyServiceImpl
- 加载实现类
public class Main {
public static void main(String[] args) {
ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {
service.doSomething();
}
}
}
Dubbo SPI是Apache Dubbo框架自带的一种SPI机制,它在Java SPI基础上进行了扩展,支持动态添加和删除实现类。Dubbo SPI的实现代码示例如下:
- 定义接口
@SPI("default")
public interface MyService {
void doSomething();
}
- 实现接口
@SPI("impl1")
public class MyServiceImpl1 implements MyService {
@Override
public void doSomething() {
System.out.println("do something by MyServiceImpl1");
}
}
@SPI("impl2")
public class MyServiceImpl2 implements MyService {
@Override
public void doSomething() {
System.out.println("do something by MyServiceImpl2");
}
}
- 配置文件
在META-INF/dubbo目录下创建一个以接口全限定名为文件名的文件,并在文件中指定实现类的名称和对应的扩展名。
代码语言:javascript复制# META-INF/dubbo/com.example.MyService
impl1=com.example.MyServiceImpl1
impl2=com.example.MyServiceImpl2
- 加载实现类
public class Main {
public static void main(String[] args) {
ExtensionLoader<MyService> loader = ExtensionLoader.getExtensionLoader(MyService.class);
MyService service = loader.getExtension("impl1");
service.doSomething();
}
}
Spring SPI是Spring框架自带的一种SPI机制,它通过在META-INF/spring.factories文件中指定实现类来实现。Spring SPI的实现代码示例如下:
- 定义接口
public interface MyService {
void doSomething();
}
- 实现接口
public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println("do something by MyServiceImpl");
}
}
- 配置文件
在META-INF/spring.factories文件中指定实现类的全限定名。
代码语言:javascript复制com.example.MyService=com.example.MyServiceImpl
- 加载实现类
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext();
MyService service = context.getBean(MyService.class);
service.doSomething();
}
}