Dubbo源码学习笔记 之 扩展机制与ExtensionLoader类

 dubbo的代码很久之前看过一遍,个人比较懒,没有做笔记总结,很多都忘了。最近抽时间仔细学习了下源码,记录总结下,加深印象。

 环境:

  源码版本: 2.7.3-SNAPSHOT 

      IDE: idea Intelij 

   1. 扩展机制 与 ExtensionLoader  类

      Dubbo 采用 的微内核+扩展的优秀设计,扩展点设计借鉴了JDK 的ServiceLoader 机制, 核心实现落在 ExtensionLoader.class ,理解这个类,对读懂、调试代码非常关键。

     ExtensiionLoader 类的成员变量如下:

    // ===============基础数据===============
    private String cachedDefaultName; //SPI 默认扩展名称
    private final Class<?> type;   //当前加载的SPI class 类型
    private final ExtensionFactory objectFactory; //对象工厂的SPI 的扩展, 用于对Extension 注入属性(set方法对象)
    
    //  =========Class 缓存=========
    private volatile Class<?> cachedAdaptiveClass = null; 
    private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
    private Set<Class<?>> cachedWrapperClasses;  //Warp扩展 class集合。 如果一个扩展的构造函数参数类型为当前扩展,则这个扩展为Wrap型

    // ==========Instance 缓存=================
    private final Holder<Object> cachedAdaptiveInstance = new Holder<>(); //Adaptive 实例缓存
    private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>(); //生成的扩展实例缓存
    
    private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>(); //Activate 扩展实例缓存

    //  =============运行时产生内容=============
    private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>(); //缓存的扩展点Class-名称  映射
    private volatile Throwable createAdaptiveInstanceError;
    private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();

    private ExtensionLoader(Class<?> type) {
        this.type = type;
        //每个ExtensionLoader (除了ExtensionFactory)都需要一个 factory, 依然采用扩展机制加载
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

  将成员变量分成基础数据, Class缓存,Instance缓存, 运行时产生的其他数据四种。

  当执行 loadExtensionClasses() 方法,遍历所有的扩展实现后,在loadClass()方法里,

一个扩展必会被 划分为adaptive、普通实现、wrap 扩展中的一种:

   1. Adaptive扩展 ,在class上面带有Adaptive注解,至多1个(如没有,在调用getAdaptiveExtension()时自动生成一个), 例如:AdaptiveExtensionFactory 类

   2. 普通扩展 , 扩展点的具体实现,例如Protocol 扩展的 DubboProtocol 扩展。

   3. wrap 扩展, 该类型的扩展,有个该扩展点的构造函数,例如 ProtocolFilterWrapper 为Protocol的扩展,有个 构造函数,需要Protocol类型的参数。 wrap扩展,是对普通扩展的包装,当生成普通扩展时,都会循环一遍wrap class,全部包装一遍。

 2. 重要方法: 

  ExtensionLoader 有2个重要的方法:getAdaptiveExtension()与 getActivateExtension()

  getAdaptiveExtension :

     adaptive扩展, 是一个包装(代理)类,会根据运行时传入url里面的key-value 值,确定最终调用的实际扩展。

    内部逻辑如下:

      如有成员变量 adaptiveClass 有值,则直接用class.newInstance() 一个实例出来,

      如果 无值,则 用String 构造一个adaptiveClass 的源码,用complier 实时编译,生成adaptive 实例。

   

 getActivateExtension:

      activate 扩展,是一个有条件的扩展,当分组 && 值满足条件时,才会被加载到。

      例如调用Invokcation的 Fitler,Group分为 provider 与consumer, 当Filter 分组取值为privider时,会被server 端构建。

//group 为provider,仅用于发布服务
//value 有值,需要在配置里面, accesslog 属性配置项有值
@Activate(group = PROVIDER, value = ACCESS_LOG_KEY)
public class AccessLogFilter implements Filter {

3. 扩展的实例化

  在dubbo里面,扩展一般都是无参构造函数,除了wrap扩展,是有个本扩展点的构造函数。

  扩展点实例化后,会注入属性。 遍历set开头的方法,查找方法的参数类型, 然后通过objectFactory 去获取对应类型的对象,完成注入。

  属性注入,在ExchangeServer、Transporter 里面比较容易看到,在最开始Debug跟踪源码的时候,经常不知道这个属性是什么时候来的,感觉莫名其妙。

  以上几个点,基本就是ExtensionLoader方法里面比较关键的部分,弄清楚以上几个点,对于微内核的运行机制,就能很清楚了。 后续就是流程组装了。

猜你喜欢

转载自www.cnblogs.com/keep-code/p/11058662.html
今日推荐