Skip to content

Implement_extension_loader

Geng Zhang edited this page Feb 18, 2017 · 2 revisions

ExtensionLoader实现细节

设计

需求

为了对RPC各个环节的都有充足的可扩展性,提供SPI的能力。 所以内部的实现和第三方实现都是绝对平等的。

接口设计

  1. 提供一个注解,可以在接口类或者抽象类上面加,表示该类为一个扩展点
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    public @interface Extensible {
    
        /**
         * 指定自定义扩展文件名称,默认就是全类名
         *
         * @return 自定义扩展文件名称
         */
        String file() default "";
    
        /**
         * 扩展类是否使用单例,默认使用
         *
         * @return 是否使用单例
         */
        boolean singleton() default true;
    
        /**
         * 扩展类是否需要编码,默认不需要
         *
         * @return 是否需要编码
         */
        boolean coded() default false;
    }
  2. 提供一个注解,表示该类为一个扩展实现
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    public @interface Extension {
        /**
         * 扩展点名字
         *
         * @return 扩展点名字
         */
        String value();
    
        /**
         * 扩展点编码,默认不需要,当接口需要编码的时候需要
         *
         * @return 扩展点编码
         * @see Extensible#coded()
         */
        byte code() default -1;
    
        /**
         * 排序,默认不需要
         *
         * @return 排序
         */
        int order() default 0;
    
    }
  3. 通过META-INF/service/bsoa下的接口描述文件来进行SPI描述

示例

  1. 指定扩展点

    @Extensible(singleton = false)
    public abstract class Client {
    }
  2. 指定扩展实现类

    @Extension("failover")
    public class FailoverClient extends AbstractClient {
    }
  3. 扩展描述文件 META-INF/services/bsoa/io.bsoa.rpc.client.Client

    failover=io.bsoa.rpc.client.FailoverClient
    或者直接
    io.bsoa.rpc.client.FailoverClient

实现

1.加载阶段

加载需要调用方法ExtensionLoader(Class<T> interfaceClass, ExtensionLoaderListener<T> listener) 主要逻辑如下:

  1. 首先读取bsoa_default.jsonbsoa.json,找到扩展描述文件存放的文件夹:extension.load.path属性
  2. 找到接口类对应的扩展描述文件的文件名(默认就是接口名,也可以自己指定)
  3. 循环加载这个文件下的扩展描述文件,按行读取。 注意:同一个接口的同一个别名对应唯一的一个实现类,不能重复。
  4. 保存扩展实现类的alias和实现类的对应关系。
  5. 如果ExtensionLoaderListener不为空,则通知Listener。

2.使用阶段

  1. 使用时调用方法 public T getExtension(String alias){}
  2. 从加载时保存的对应关系中找到实现类。
  3. 如果扩展点是单例模式的,那么返回单例,否则返回一个新的实例
Clone this wiki locally