怎么将dubbo的SPI移植到开源项目中,附dubbo的ExtensionLoader<T> 的实现原理分析

58 篇文章 0 订阅
32 篇文章 1 订阅

Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。

Dubbo改进了JDK标准的SPI的以下问题:

  • JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
  • 如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK标准的ScriptEngine,通过getName();获取脚本类型的名称,但如果RubyScriptEngine因为所依赖的jruby.jar不存在,导致RubyScriptEngine类加载失败,这个失败原因被吃掉了,和ruby对应不起来,当用户执行ruby脚本时,会报不支持ruby,而不是真正失败的原因。
  • 增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。

具体怎么实现:

第一步就是上去git下载dubbo的源码做参考

https://github.com/alibaba/dubbo


1。通过加载类获取加载类的classloader去把classpath目录下的所有配置拿到手,然后再Class.forName(类全名, true, classLoader)拿到clazz,才通过clazz.newInstance()获取实例对象,在加载扩展类的时候如果其成员变量也是扩展类型的,则会通过setter自动加载实现,实现对IoC和AOP支持;
出处:com.alibaba.dubbo.common.extension.ExtensionLoader的
loadFile(Map<String, Class<?>> extensionClasses, String dir) 方法
 
以及
com.alibaba.dubbo.common.extension.ExtensionLoader的
T injectExtension(T instance)
方法

2.为了避免在注入扩展点的时候初始化暂时不用的扩展类上花太多时间(或内存),所有的扩展点采用精简的适配类代替。在获取精简适配类的时候会先检测是否存在已定义的适配类,如果有就直接应用,如果没有就使用javassist等编译工具生成适配类代理,适配类代理的所有代理方法如果有指定某一扩展类的方法则才有该扩展类的方法,没有的话,则才有默认扩展类相应的方法代理实现,如果没有默认扩展类则抛出异常。
出处:
com.alibaba.dubbo.common.extension.ExtensionLoader的
getExtensionClasses()用于加载自定义的适配类
如果自定义的适配类不存在就用javassist等工具去动态生成一个适配类
出处:
com.alibaba.dubbo.common.extension.ExtensionLoader
private Class<?> getAdaptiveExtensionClass() {
    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
com.alibaba.dubbo.common.extension.ExtensionLoader的createAdaptiveExtensionClass()方法用于字节码生成适配类。



3.扩展点默认有且只会加载一个“扩展点的适配类”,如果想要加载多个扩展类(比如多个filter类),可以在想要被加载的扩展类实现加上注解@Activate,表示该类必须要激活(同时也表示这个扩展类可以存在多个扩展类实现)。

出处:com.alibaba.dubbo.common.extension.ExtensionLoader的
loadFile(Map<String, Class<?>> extensionClasses, String dir) 方法

上面三点中,

第一点,利用classloader实现了SPI功能,同时加入了IoC和AOP的“级联加载”;

第二点,利用字节码工程实现了“懒加载”扩展类,以及加载异常的报备;

第三点,采用@Activate注解实现,扩展点的“单例加载”和“”多例加载“”双模切换的功能。


如果只是想要移植SPI功能,只需要会用classLoader就可以了。

如果要想要实现懒加载就要引入轻量级的适配类功能。

如果想要实现单例多例切换就引入@Activate注解。


具体实现细节疑问可以在评论中留下。


OpenExtensionLoader开源地址:

https://github.com/bigcai/OpenExtensionLoader.git 点击打开链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值