图解Dubbo,六种扩展机制详解( 二 )

Dubbo使用了JAVA的SPI(Service Provider Interface)扩展机制 。SPI是JDK内置的一种服务发现机制 , 其具体实现方式是在资源文件META-INF/services中通过名称为SPI接口的全限定类名创建一个文本文件 , 在这个文本文件中可以写入该SPI接口的实现类全限定类名 , 这样可以实现动态加载实现类的目的 。
?Dubbo中的SPI扩展机制能够在不修改核心源代码的前提下 , 通过修改配置文件或者实现自定义拓展类的方式来替换或增加核心功能 。
下图描述了 Dubbo SPI 扩展机制的工作流程:
图解Dubbo,六种扩展机制详解

文章插图
SPI 扩展机制
【图解Dubbo,六种扩展机制详解】上图描述了 Dubbo SPI 扩展机制的工作流程 , 其中:
  1. 用户向 Dubbo Framework 请求获取 ExtensionLoader , ExtensionLoader 是 Dubbo SPI 扩展机制的核心类;
  2. Dubbo Framework 加载 ExtensionLoader , 并返回给用户;
  3. 用户调用 ExtensionLoader 的方法;
  4. ExtensionLoader 根据指定的 Extension 接口 , 通过 SPI 机制加载 Extension 实现;
  5. Extension 实现将被加载 , ExtensionLoader 返回 Extension 实现给用户;
2、SPI扩展机制的使用示例首先 , 我们需要定义一个SPI扩展接口 , 让Dubbo的扩展实现类都实现该接口 。
示例代码:
package com.example.extension;import com.alibaba.dubbo.common.extension.SPI;@SPI("default")public interface PrintService {void print(String msg);} 
在接口上添加@SPI注解 , 指定该扩展的默认实现类 。
然后 , 我们需要在META-INF/services目录下创建一个“接口全限定类名”的文件名的文件 , 文件中写入我们实现的SPI扩展类的全限定类名 。
比如我们需要同过实现PrintService接口来实现打印功能 , 那么我们在META-INF/services/目录下创建一个名为“com.example.extension.PrintService”的文件 , 文件内容为:
 
com.example.extension.impl.ConsolePrintServiceImpl 
接下来 , 我们就可以通过Dubbo框架自动加载通过SPI机制注册的实现类了 。
示例代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);PrintService printService =ExtensionLoader.getExtensionLoader(PrintService.class).getDefaultExtension();printService.print("hello world!"); 
以上代码中 , 我们使用Dubbo的扩展加载器ExtensionLoader来获取PrintService接口的默认实现类 , 然后调用该实现类的print()方法即可实现打印功能 。
3、Dubbo的SPI扩展机制中自定义扩展点的实现示例在Dubbo框架中 , 我们可以通过自定义扩展点来增强Dubbo的功能 。
自定义扩展点需要实现Dubbo提供的ExtensionFactory接口 , 并在META-INF/dubbo/internal/?路径下创建一个文件名为com.alibaba.dubbo.common.extension.ExtensionFactory的文件 , 文件中写入扩展点实现类的全限定类名 。
示例代码:
 
package com.example.extension;import com.alibaba.dubbo.common.extension.ExtensionFactory;public class MyExtensionFactory implements ExtensionFactory {@Overridepublic <T> T getExtension(Class<T> type, String name) {if (type.equals(PrintService.class)) {return (T) new ConsolePrintServiceImpl();}return null;}} 
在MyExtensionFactory中实现getExtension()方法 , 并根据type参数判断获取哪个扩展实现类 。
在本示例中 , 我们仅仅实现了PrintService接口的实现类 , 因此只需要判断type参数是否为PrintService类即可 。
下一步 , 我们需要在META-INF/dubbo/internal/目录下创建一个名为com.alibaba.dubbo.common.extension.ExtensionFactory的文件 , 文件内容为我们实现的扩展点实现类全限定类名 。
比如我们实现的扩展点实现类为com.example.extension.MyExtensionFactory? , 那么我们就要在META-INF/dubbo/internal/目录下创建一个名为com.alibaba.dubbo.common.extension.ExtensionFactory?的文件 , 并将文件内容写为com.example.extension.MyExtensionFactory 。
最后 , 我们在程序中就可以使用自定义的扩展点了 。示例代码:


推荐阅读