ToB企服应用市场:ToB评测及商务社交产业平台

标题: SPI机制 [打印本页]

作者: 莱莱    时间: 2024-11-27 02:58
标题: SPI机制
概述

Java SPI(Service Provider Interface)是一种 服务发现机制,用于实现模块化、可插拔式的设计。在 Java 中,它允许步伐在运行时动态地加载和调用实现类,而不是在编译时硬编码依赖。这种机制在 JDK 内置库第三方库 中被广泛使用,比方 JDBC 驱动加载、日志框架绑定(如 SLF4J 和 Logback)、序列化机制扩展等。
SPI 的核心概念

SPI 的工作机制

Java SPI 的实现依赖于 resources/META-INF/services 文件夹中的描述文件。重要过程如下:
Java SPI 示例

我的文件结构定义如下:
  1. /src/
  2.     ├── test/
  3.             ├── java/
  4.                     ├── spi/
  5.                             ├── example/
  6.                                     ├── MyService                # SPI接口
  7.                                     ├── SericeA                        # SPI接口A实现
  8.                                     ├── SericeB                        # SPI接口B实现
  9.                                     ├── SPIServiceLoader # SPI加载器
  10.     ├── resources/
  11.             ├── META-INF/
  12.                     ├── services/
  13.                             ├── spi.example.MyService        # 资源文件
复制代码
定义服务接口

创建一个服务接口 MyService:
  1. package spi.example;
  2. public interface MyService {
  3.     void execute();
  4. }
复制代码
创建服务提供者

创建ServiceA、SeriviceB两个类,然后重写excute代码
  1. package spi.example;
  2. public class ServiceA implements MyService {
  3.     @Override
  4.     public void execute() {
  5.         System.out.println("ServiceA is executing...");
  6.     }
  7. }
复制代码
  1. package spi.example;
  2. public class ServiceB implements MyService {
  3.     @Override
  4.     public void execute() {
  5.         System.out.println("ServiceB is executing...");
  6.     }
  7. }
复制代码
配置服务提供者

在 resources/META-INF/services 目录下,创建一个文件,文件名为 spi.example.MyService,内容为:
  1. spi.example.ServiceA
  2. spi.example.ServiceB
复制代码
使用 ServiceLoader 加载服务
在主步伐中,通过 ServiceLoader 动态加载实现类:
  1. package spi.example;
  2. import java.util.ServiceLoader;
  3. public class SPIServiceLoader {
  4.     public static void main(String[] args) {
  5.         ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
  6.         for (MyService service : loader) {
  7.             service.execute();
  8.         }
  9.     }
  10. }
复制代码
运行结果


SPI恶意代码实行

比如我们在spi.example包中新增一份恶意代码的MyService实现,如下:
  1. package spi.example;
  2. public class EvilService implements MyService{
  3.     public EvilService(){
  4.         try {
  5.             System.out.println("EvilService constructor is executing...");
  6.             Runtime.getRuntime().exec("calc");
  7.         }catch (Exception ignore) { }
  8.     }
  9.     @Override
  10.     public void execute() {
  11.         System.out.println("EvilService is executing...");
  12.     }
  13. }
复制代码
运行结果如下,可以看到恶意代码被实行:

SPI 的缺点

增强版 SPI

为相识决上述缺点,当代框架(如 Spring)提供了增强的服务发现机制。比方:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4