1、简述
Apache Dubbo 是一款高性能的分布式服务框架,它扩展了 Java SPI 的机制,提供了更灵活的服务发现和加载机制。Dubbo SPI 相较于 Java SPI 具有 更强的扩展性 和 更高的性能,通过其增强的能力可以实现服务的自定义加载逻辑、自动注入、AOP 等功能。
样例代码: https://gitee.com/lhdxhl/springboot-example.git
本文将详细讲解 Dubbo SPI 的机制、基础实现步骤以及高级特性的使用方法,并通过具体示例展示其强大功能。

2、Dubbo SPI 的核心概念
🔥 @SPI 注解
声明接口为 SPI 接口,可指定默认实现。
🔥 @Adaptive 注解
用于生成动态代理类,代理逻辑通过参数动态选择扩展实现。
🔥 ExtensionLoader
Dubbo 的扩展加载器,用于加载和管理扩展点。
🔥 自动注入
支持在扩展点中注入其他依赖。
Dubbo SPI 与 Java SPI 的对比:
| 特性 | Java SPI | Dubbo SPI |
|---|---|---|
| 配置文件位置 | META-INF/services |
META-INF/dubbo 下的多个目录 |
| 多实现选择机制 | 加载所有实现类 | 支持自动加载、默认实现、按名称加载等 |
| 注解支持 | 不支持 | 支持 @SPI 注解 |
| 自动注入 | 不支持 | 支持依赖注入 |
| AOP 与装饰器模式支持 | 不支持 | 支持通过 @Adaptive 实现动态代理和扩展能力 |
3、Dubbo SPI 的基础用法
在使用 Dubbo 之前,需要添加其依赖。以下是 Dubbo 的 Maven 依赖:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.15</version>
</dependency>
3.1 定义 SPI 接口
使用 @SPI 注解声明接口,并可指定默认实现:
package com.example.dubbo.spi;
import org.apache.dubbo.common.extension.SPI;
@SPI("english")
public interface GreetingService {
void sayHello(String name);
}
3.2 实现 SPI 接口
实现类 1(默认实现):
package com.example.dubbo.spi.impl;
import com.example.dubbo.spi.GreetingService;
public class EnglishGreetingService implements GreetingService {
@Override
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
实现类 2:
package com.example.dubbo.spi.impl;
import com.example.dubbo.spi.GreetingService;
public class ChineseGreetingService implements GreetingService {
@Override
public void sayHello(String name) {
System.out.println("你好, " + name + "!");
}
}
3.3 配置文件
在 resources/META-INF/dubbo/com.example.dubbo.spi.GreetingService 文件中添加如下内容:
english=com.example.dubbo.spi.impl.EnglishGreetingService
chinese=com.example.dubbo.spi.impl.ChineseGreetingService
3.4 使用 ExtensionLoader 加载扩展点
package com.example.dubbo.spi;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class DubboSPIDemo {
public static void main(String[] args) {
// 获取扩展加载器
ExtensionLoader<GreetingService> loader = ExtensionLoader.getExtensionLoader(GreetingService.class);
// 加载默认实现
GreetingService defaultService = loader.getDefaultExtension();
defaultService.sayHello("Java Developer");
// 加载指定实现
GreetingService chineseService = loader.getExtension("chinese");
chineseService.sayHello("Java Developer");
}
}
运行结果:
Hello, Java Developer!
你好, Java Developer!
4、Dubbo SPI 的高级特性
4.1 @Adaptive 动态代理示例
在接口方法中动态选择实现,修改接口:
package com.example.dubbo.spi;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.SPI;
@SPI("english")
public interface GreetingService {
@Adaptive
void sayHello(String name);
}
修改 META-INF/dubbo/com.example.dubbo.spi.GreetingService:
english=com.example.dubbo.spi.impl.EnglishGreetingService
chinese=com.example.dubbo.spi.impl.ChineseGreetingService
adaptive=com.example.dubbo.spi.impl.AdaptiveGreetingService
添加自定义 @Adaptive 实现:
package com.example.dubbo.spi.impl;
import com.example.dubbo.spi.GreetingService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
@Adaptive
public class AdaptiveGreetingService implements GreetingService {
@Override
public void sayHello(String name) {
URL url = new URL("dubbo", "localhost", 8080);
String greetingType = url.getParameter("greeting", "english");
GreetingService service = ExtensionLoader.getExtensionLoader(GreetingService.class).getExtension(greetingType);
service.sayHello(name);
}
}
动态调用:
package com.example.dubbo.spi;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class AdaptiveSPIDemo {
public static void main(String[] args) {
GreetingService adaptiveService = ExtensionLoader.getExtensionLoader(GreetingService.class).getAdaptiveExtension();
adaptiveService.sayHello("Dynamic");
}
}
运行时,根据 URL 参数选择不同的实现。
4.2 自动注入示例
定义一个依赖的扩展接口:
package com.example.dubbo.spi;
import org.apache.dubbo.common.extension.SPI;
@SPI
public interface LoggerService {
void log(String message);
}
实现 LoggerService:
package com.example.dubbo.spi.impl;
import com.example.dubbo.spi.LoggerService;
public class ConsoleLoggerService implements LoggerService {
@Override
public void log(String message) {
System.out.println("[LOG] " + message);
}
}
修改 GreetingService 的实现以注入 LoggerService:
package com.example.dubbo.spi.impl;
import com.example.dubbo.spi.GreetingService;
import com.example.dubbo.spi.LoggerService;
import org.apache.dubbo.common.extension.Inject;
public class EnglishGreetingService implements GreetingService {
@Inject
private LoggerService loggerService;
@Override
public void sayHello(String name) {
loggerService.log("Greeting in English: " + name);
System.out.println("Hello, " + name + "!");
}
}
4.3 AOP 与装饰器模式示例
定义装饰器:
package com.example.dubbo.spi.decorator;
import com.example.dubbo.spi.GreetingService;
public class GreetingServiceDecorator implements GreetingService {
private final GreetingService delegate;
public GreetingServiceDecorator(GreetingService delegate) {
this.delegate = delegate;
}
@Override
public void sayHello(String name) {
System.out.println("[Decorator] Before greeting...");
delegate.sayHello(name);
System.out.println("[Decorator] After greeting...");
}
}
在加载时动态装饰:
GreetingService original = loader.getExtension("english");
GreetingService decorated = new GreetingServiceDecorator(original);
decorated.sayHello("Decorator Example");
5、总结
Dubbo SPI 是 Java SPI 的强大扩展,提供了更多动态能力和功能,包括:
🔥 动态代理 (@Adaptive)。
🔥 依赖注入 (@Inject)。
🔥 插件化架构支持。
🔥 装饰器模式实现。
通过 Dubbo SPI,可以更加灵活地实现模块化和插件化开发,非常适合分布式系统中动态服务的加载和管理。希望本文对您理解 Dubbo SPI 机制有所帮助!