RPC框架Motan 1. ExtensionLoader模块介绍

176 阅读3分钟

一、前言

extensionLoader位于motan-core包下,用于获取指定接口的动态实现类对象。

二、方法介绍

2. 1 getExtensionLoader方法

获取接口的ExtensionLoader对象

  1. 校验是否为有效java接口
  2. SPI注解修饰
  3. 从容器对象extensionLoaders中获取接口的ExtensionLoader对象
  4. ExtensionLoader对象不存在则创建接口的ExtensionLoader对象并放到容器对象中,同时返回ExtensionLoader对象

2.2 loadExtensionClasses方法

初始化接口的扩展名和实现类类对象关系,扩展名和实现类对象单例对象映射关系

  1. 根据指定文件名加载实现类名称

  2. 通过反射实例化接口的实现类,这里通过调用loadClass方法实现

  3. 校验实现类信息

    • public定义的类
    • 构造函数存在且public修饰且0参
    • 实现类转换成接口
  4. 获取扩展点名称

    • 实现类使用SpiMeta注解标识扩展名,优先使用注解。否则使用实现类类名
  5. 最终完成初始化extensionClasses属性扩展名和和实现类类对象的映射关系,初始化singletonInstances

2.3 getExtensionClass方法

通过扩展名获取实现类类型

2.4 getExtension方法

通过扩展名获取实现对象

  1. 获取接口上SPI注解标识的实例类型(单例模式,多利模式)

  2. 单例模式

    • 根据扩展名获取单例池中的实例对象,如果存在直接返回
    • 根据扩展名获取实例类类对象
    • 通过实现类类对象反射机制得到实现类对象并放到单例池中,同时返回实例化对象
  3. 多例模式

    • 根据扩展名获取实例类类对象
    • 通过实现类类对象反射机制得到实现类对象,返回实例化对象

2.5 addExtensionClass方法

向extensionClasses属性中添加指定接口的实现类的扩展名和和实现类类对象的映射关系。与loadExtensionClasses方法处理流程一致。

2.6 getExtensions方法

返回指定key的实现排序列表

  1. key为空,则直接添加现有实现类到返回排序列表
  2. 实现类被Activation注解修饰,且Activation注解的key属性值存在,添加与参数key相同的实现类对象到返回排序列表
  3. 对返回的列表进行排序
  4. 返回排序好的列表

三、示例

3.1 单例模式

定义接口

@Spi(scope = Scope.SINGLETON) // 指定单例模式
public interface SpiTestInterface {
    long spiHello();
}

接口实现类

@SpiMeta(name = "spitest") // 指定实现类的扩展名称
public class SpiTestImpl implements SpiTestInterface {
    private static AtomicLong counter = new AtomicLong(0);
    private long index = 0;
​
    public SpiTestImpl() {
        index = counter.incrementAndGet();// 每次执行构造函数index加1
    }
​
    @Override
    public long spiHello() {
        return index;
    }
​
}

调用代码

SpiTestInterface singleton1 = ExtensionLoader.getExtensionLoader(SpiTestInterface.class).getExtension("spitest");
SpiTestInterface singleton2 = ExtensionLoader.getExtensionLoader(SpiTestInterface.class).getExtension("spitest");
​
long l1 = singleton1.spiHello();
long l2 = singleton2.spiHello();

image.png

3.2 多例模式

定义接口

@Spi(scope = Scope.PROTOTYPE) // 多例模式
public interface SpiPrototypeInterface {
    long spiHello();
}

定义接口实现类

@SpiMeta(name = "spiPrototypeTest") // 实现类扩展名称
public class SpiPrototypeTestImpl implements SpiPrototypeInterface {
    private static AtomicLong counter = new AtomicLong(0);
    private long index = 0;
​
    public SpiPrototypeTestImpl() {
        index = counter.incrementAndGet();
    }
​
    @Override
    public long spiHello() {
        return index;
    }
​
}

调用代码

SpiPrototypeInterface prototype1 = ExtensionLoader.getExtensionLoader(SpiPrototypeInterface.class).getExtension("spiPrototypeTest");
SpiPrototypeInterface prototype2 = ExtensionLoader.getExtensionLoader(SpiPrototypeInterface.class).getExtension("spiPrototypeTest");
long p1 = prototype1.spiHello();
long p2 = prototype2.spiHello();

image.png

3.4 添加实现类

定义接口类实现

@SpiMeta(name = "spiPrototypeTest2") // 实现类扩展名称
public class SpiPrototypeTestImpl2 implements SpiPrototypeInterface {
    private static AtomicLong counter = new AtomicLong(0);
    private long index = 0;
​
    public SpiPrototypeTestImpl2() {
        index = counter.incrementAndGet();
    }
​
    @Override
    public long spiHello() {
        System.out.println("SpiPrototypeTestImpl_" + index + " say hello");
        return index;
    }
​
}

调用代码

        List<SpiPrototypeInterface> extensions = ExtensionLoader.getExtensionLoader(SpiPrototypeInterface.class).getExtensions("");
        int size = extensions.size();// 1
        ExtensionLoader loader = ExtensionLoader.getExtensionLoader(SpiPrototypeInterface.class);
        loader.addExtensionClass(SpiPrototypeTestImpl2.class);
​
        extensions = ExtensionLoader.getExtensionLoader(SpiPrototypeInterface.class).getExtensions("");
        size = extensions.size();// 2