文章目录

  • ​​1.jdk spi 机制​​
  • ​​2.dubbo spi机制​​

1.jdk spi 机制

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_ide

SomeService:

package com.abc.service;

public interface SomeService {
void hello();
}

OneServiceImpl

public class OneServiceImpl implements SomeService {
@Override
public void hello() {
System.out.println("执行OneServiceImpl的hello()方法");
}
}

TwoServiceImpl

public class TwoServiceImpl implements SomeService {
@Override
public void hello() {
System.out.println("执行TwoServiceImpl的hello()方法");
}
}

SPITest

public class SPITest {
public static void main(String[] args) {
// load()中放的是业务接口,其就相当于要加载的配置文件名
ServiceLoader<SomeService> loader = ServiceLoader.load(SomeService.class);
Iterator<SomeService> it = loader.iterator();
while (it.hasNext()) {
SomeService service = it.next();
service.hello();
}
}
}

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_加载_02

ServiceLoader.load():

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_java_03

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_zookeeper_04

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_加载_05

迭代器方法:

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_zookeeper_06

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_加载_07

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_rpc_08

jdk的spi的缺点为不可以是懒加载, 就是说必须全部加载然后for循环。

2.dubbo spi机制

key=value模式, 可以指定多个key

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_java_09

这里的目录结构为 3种

  • META-INF/dubbo/internal
  • META-INF/dubbo
  • META-INF/services

Order

@SPI("alipay")
public interface Order {
// 支付方式
String way();
}

AlipayOrder

public class AlipayOrder implements Order {
@Override
public String way() {
System.out.println("--- 使用支付宝支付 ---");
return "支付宝支付";
}
}

WechatOrder

public class WechatOrder implements Order {
@Override
public String way() {
System.out.println("--- 使用微信支付 ---");
return "微信支付";
}
}

OrderTest

public class OrderTest {

@Test
public void test01() {
// 获取到用于加载Order类型扩展类实例的extensionLoader实例
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);

Order alipay = loader.getExtension("alipay");
System.out.println(alipay.way());

Order wechat = loader.getExtension("wechat");
System.out.println(wechat.way());
}

@Test
public void test02() {
// 获取到用于加载Order类型扩展类实例的extensionLoader实例
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
Order wechat2 = loader.getExtension("wechat2");
System.out.println(wechat2.way());

Order wechat = loader.getExtension("wechat");
System.out.println(wechat.way());

}
方法@Test
public void test03() {
// 获取到用于加载Order类型扩展类实例的extensionLoader实例
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);

// 以下方式都会报错
// Order alipay = loader.getExtension(null);
// Order alipay = loader.getExtension("");

// 以下方式不会报错,其会加载SPI接口指定的默认名称的扩展类,
// 但SPI接口默认名称不是这样使用的
Order alipay = loader.getExtension("true");
System.out.println(alipay.way());

}
}

因为Order的spi注解上面默认的是​​alipay​

所以如果是test03的话给定的是true的话则为alipayOrder的方法。

深度解析dubbo源码 (dubbo spi实现和jdk spi实现) (一)_rpc_10

ExtensionLoader.getExtensionLoader():

先获取到实例, 然后getExtension()方法获取到接口的实现类。