通过一个简单的例子来了解一下Java的SPI机制:
1、写了一个接口。
package com.common.study; import com.alibaba.dubbo.common.extension.SPI; /** * @Interface DubboJavaRoot * @Description TODO * @Author xuyang7 * @Date 2019/5/22 11:40 * @Version 1.0 **/ //@SPI public interface DubboJavaRoot { void sayHello(); }
2、然后写两个实现类:
package com.common.study.impl; import com.common.study.DubboJavaRoot; /** * @ClassName JavaSPIImp1 * @Description TODO * @Author xuyang7 * @Date 2019/5/22 11:42 * @Version 1.0 **/ public class JavaSPIImp1 implements DubboJavaRoot { @Override public void sayHello() { System.out.println("Hello, I am JavaSPIImp1."); } } package com.common.study.impl; import com.common.study.DubboJavaRoot; /** * @ClassName JavaSPIImp2 * @Description TODO * @Author xuyang7 * @Date 2019/5/22 11:42 * @Version 1.0 **/ public class JavaSPIImp2 implements DubboJavaRoot { @Override public void sayHello() { System.out.println("Hello, I am JavaSPIImp2."); } }3、然后在 src/main/resources/ 下建立 /META-INF/services 目录创建一个以接口引用为名称的文件内容为两个实现类的引用:
com.common.study.impl.JavaSPIImp1 com.common.study.impl.JavaSPIImp2文件层次如下:
创建执行类:
public class JavaSPITest { public static void main(String[] args) { ServiceLoader<DubboJavaRoot> serviceLoader = ServiceLoader.load(DubboJavaRoot.class); System.out.println("Java SPI"); serviceLoader.forEach(DubboJavaRoot::sayHello); } }执行结果如下:
ServiceLoader代码了解:
Dubbo自己实现了一套SPI机制,并没有使用Java的SPI机制:
1、我们要在接口类上添加注解@SPI:
@SPI public interface DubboJavaRoot { void sayHello(); }2、编写接口实现类:
package com.common.study.impl; import com.common.study.DubboJavaRoot; /** * @ClassName DubboSPIImp1 * @Description TODO * @Author xuyang7 * @Date 2019/5/22 11:42 * @Version 1.0 **/ public class DubboSPIImp1 implements DubboJavaRoot { @Override public void sayHello() { System.out.println("Hello, I am DubboSPIImp1."); } } package com.common.study.impl; import com.common.study.DubboJavaRoot; /** * @ClassName DubboSPIImp2 * @Description TODO * @Author xuyang7 * @Date 2019/5/22 11:42 * @Version 1.0 **/ public class DubboSPIImp2 implements DubboJavaRoot { @Override public void sayHello() { System.out.println("Hello, I am DubboSPIImp2."); } }3、然后 我们需要建立一个在 src/main/resources/ 下建立 /META-INF/dubbo目录创建一个以接口引用为名称的文件内容为两个实现类的引用:
impldubbo1 = com.common.study.impl.DubboSPIImp1 impldubbo2 = com.common.study.impl.DubboSPIImp24、编写测试类:
public class JavaSPITest { public static void main(String[] args) { JavaSPITest javaSPITest = new JavaSPITest(); javaSPITest.loadDubbo(); } public void loadDubbo(){ ExtensionLoader<DubboJavaRoot> extensionLoader = ExtensionLoader.getExtensionLoader(DubboJavaRoot.class); DubboJavaRoot optimusPrime = extensionLoader.getExtension("impldubbo1"); optimusPrime.sayHello(); DubboJavaRoot bumblebee = extensionLoader.getExtension("impldubbo2"); bumblebee.sayHello(); } }结果如下:
在建立META-INF下面的文件时 不一定非要在dubbo下,dubbo扫描时根据ExtensionLoader中的代码如下:
所以我们只要注意根据这些建立就可以了。与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置。这里需要注意一下。