SOFA RPC源码解析之扩展机制ExtensionLoader

1.SOFA RPC源码解析

1.1  扩展机制

1.1.1  简述

        SOFA RPC的扩展点加载机制是从JDK标准的SPI扩展点发现机制加强而来。

        SPI,全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。

        SPI是上游产商给服务供应商提供的接口,供应商遵循接口契约提供自己的实现。供应商提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里创建一个以服务接口命名的文件,该文件里就是实现该服务接口的具体实现类。当外部程序装配这个模块的时候,通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

        基于这样一个约定,可以很好的找到服务接口的实现类,而不需要再代码里制定。

        Java SPI机制的约定和使用方法如下图所示:

        Java SPI机制的约定:

        1.   在META-INF/services/目录中创建以接口全限定名命名的文件该文件内容为API具体实现类的全限定名;

        2.   使用ServiceLoader类动态加载META-INF中的实现类;

        3.   如SPI的实现类为Jar,则需要放在主程序classPath中;

        4.   API具体实现类必须有一个不带参数的构造方法;

        简单地了解了Java SPI服务扩展机制以后,我们再看看SOFA RPC的扩展点加载机制的类图:

        SOFA RPC扩展机制的说明:

        1.   定义接口或抽象类,并在类上增加@Extensible注解;

        2.   定义接口或抽象类的具体实现类,并在类上增加@Extension注解;

        3.   在META-INF/services/sofa-rpc目录中,创建以接口全限定名命名的文件,例如:com.alipay.sofa.rpc.module.Module。该文件内容为key-value键值对,key为实现类别名,value为API具体实现类的全限定名,例如:fault-tolerance=com.alipay.sofa.rpc.module.FaultToleranceModule;

        4.  使用ExtensionLoaderFactory获取指定接口的ExtensionLoader实例,例如:ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class);

        5.   通过ExtensionLoader类getExtension(Stringalias)方法动态加载META-INF中的实现类对应的实例,例如loader.getAllExtensions(“fault-tolerance”);

        6.   如具体实现类为Jar,则需要放在主程序classPath中;

        7.   API具体实现类必须有一个不带参数的构造方法;

1.1.2 源码解析

        以加载模块接口Module的实现类为例,详细说明RPC中的扩展机制。

1.  ExtensionLoader<Module> loader =ExtensionLoaderFactory.getExtensionLoader(Module.class)
2.  loader.getAllExtensions()

        从上述代码可以看出,使用RPC扩展机制获取指定接口的具体实现类,主要包括两大步骤:

        一、  获取指定接口对应的ExtensionLoader

        从ExtensionLoaderFactory开始,该类是ExtensionLoader的工厂类,负责根据接口名称获取指定接口对应的ExtensionLoader。

1.  public static <T>ExtensionLoader<T> getExtensionLoader(Class<T> clazz,ExtensionLoaderListener<T> listener) {
2.          ExtensionLoader<T> loader =LOADER_MAP.get(clazz);
3.          if (loader == null) {
4.              synchronized (ExtensionLoaderFactory.class){
5.                  loader = LOADER_MAP.get(clazz);
6.                  if (loader == null) {
7.                      loader = new ExtensionLoader<T>(clazz,listener);
8.                      LOADER_MAP.put(clazz,loader);
9.                  }
10.             }
11.         }
12.         return loader;
13.     }

        getExtensionLoader方法涉及的主要变量描述:

        1.   listener:ExtensionLoaderListener接口的实现类,当扩展点加载时,可以做一些额外处理工作,例如解析code,初始化等操作;

        2.   clazz:含有@Extensible注解的接口;

        3.   LOADER_MAP:全局变量,缓存已经加载的指定接口的ExtensionLoader;

        首先,从LOADER_MAP获取指定接口的ExtensionLoader。如果存在,直接返回获取到的指定接口的ExtensionLoader;否则,创建新的ExtensionLoader;

1.  public ExtensionLoader(Class<T>interfaceClass, ExtensionLoaderListener<T> listener) {
2.          this(interfaceClass, true, listener);
3.      }

        调用ExtensionLoader的构造函数:

1.  protected ExtensionLoader(Class<T>interfaceClass, boolean autoLoad, ExtensionLoaderListener<T> listener) {
2.          ……
3.          // 接口为空,既不是接口,也不是抽象类
4.          if (interfaceClass == null ||
5.              !(interfaceClass.isInterface() ||Modifier.isAbstract(interfaceClass.getModifiers()))) {
6.              throw newIllegalArgumentException("Extensible class must be interface or abstractclass!");
7.          }
8.          this.interfaceClass = interfaceClass;
9.          this.interfaceName =ClassTypeUtils.getTypeStr(interfaceClass);
10.         this.listener = listener;
11.         Extensible extensible = interfaceClass.getAnnotation(Extensible.class);
12.         if (extensible == null) {
13.             throw new IllegalArgumentException(
14.                 "Error when loadextensible interface " + interfaceName + ", must add annotation@Extensible.");
15.         } else {
16.             this.extensible = extensible;
17.         }
18.  
19.        
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任性之闲来无事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值