Dubbo自定义标签和扩展点

       Alibaba   Dubbo是开源的分布式服务治理框架,提供了服务注册,服务发现,动态配置和路由的功能。

Spring自定义标签

通过自定义标签,跟Spring无缝结合,自定义标签需要两个部分:在项目的resource/META-INF包里面配置2个文件spring.handlers和spring.schemas

spring.handlers 的内容:

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

定义了解析标签的类com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

spring.schemas的内容:

http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

用一个url来映射我们配置好的文件

dubbo.xsd的内容:

DubboNamespaceHandler继承了Spring的NamespaceHandlerSupport接口 init方法注册了各个标签的解析器 ,根据解析生成对应的BeanDefinition,这样就可以在Spring中使用自定义的标签

扩展点

JDK的ServiceLoader

JDK提供给我们一套扩展点机制,通过ServiceLoader遍历所有jar查找META-INF/services目录下实现某个接口的实现类,现在以Spark中的一个例子说明

       这里就用ServiceLoader加载所有的DataSourceRegister然后判断每个对象的shortName()是否给定的值,这样我们可以实现自己的数据源。

Dubbo的ExtensionLoader

我们一般用ExtensionLoader.getExtensionLoader(***.class)开始获取扩展点。

type 必须不为空且为接口还得有SPI注解,先从缓存中有该接口对应的ExtensionLoader,如果没有的话new一个 ,然后放进缓存中。返回这个ExtensionLoader。

看一下实例化的过程:

会用到ExtensionFactory接口的Adaptive实现 看一下getAdaptiveExtension方法

先判断是否已经存在,然后加锁再判断,如果依旧不存在,调用createAdaptiveExtension方法生成一个并缓存。

cachedClasses定义:

如果还没有设置则调用loadExtensionClasses方法加载

先判断SPI注释中参数不能大于1,赋值给成员变量cachedDefaultName,作为缺省的实现

loadFile方法中三个常数如下:

看一下loadFile:

先读取文件中的内容


根据配置反射得出clazz

clazz必须是type的实现类,如果有Adaptive注解则判断cachedAdaptiveCalss是否为空,如果为空,赋值给cachedAdaptiveCalss,否则系统中会有两个cachedAdaptiveCalss,抛出异常提示。

这里根据type接口作为参数找到一个包装类,如果有则加入wrapper这个Set中,这里的ConcurrentHashSet是Dubbo自己根据JDK的ConcurrentHashMap实现的

如果不是包装类

这里主要是给cachedActivities加入有Activite注解的类,并且映射class和name以及name和class。

返回前面getAdaptiveExtensionClass方法,如果我们前面缓存了cachedAdaptiveClass就直接返回cachedAdaptiveClass。调用injectExtension方法进行注入:

通过反射给set调用set方法赋值。

如果没有cachedAdaptiveClass则通过字节码生成器生成

需要至少有一个方法有Adaptive注解

实现的思想是根据方法的参数URL,Invocation等不同加载对同的扩展点

比如:Protocol生成以下:

class Protocol$Adpative implements Protocol{  

    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException{  

if (arg0 == null)  {   

throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invokerargument == null");   

        }  

        if (arg0.getUrl() == null) {   

            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");   

        }  

com.alibaba.dubbo.common.URLurl = arg0.getUrl();  

StringextName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );  

if(extName == null) {  

            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");   

        }  

com.alibaba.dubbo.rpc.Protocolextension = (com.alibaba.dubbo.rpc.Protocol)com.alibaba.dubbo.common.ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);  

        return extension.export(arg0);  

    }  


    public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException{  

if (arg1 == null)  {   

throw new IllegalArgumentException("url == null");   

        }  

com.alibaba.dubbo.common.URLurl = arg1;  

StringextName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );  

if(extName == null) {  

            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");   

        }  

com.alibaba.dubbo.rpc.Protocolextension = (com.alibaba.dubbo.rpc.Protocol)com.alibaba.dubbo.common.ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);  

        return extension.refer(arg0, arg1);  

    }

看一下getExtension

如果缓存有则返回,没有则调用createExtension生成一个在缓存

先对该name的扩展点实例化,然后判断时候有Wrapper的包装类,如果有,则一层层包装,最后返回一个包装类,而不是name的扩展点实例,这里我们可以实现自己的逻辑。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 总结:Protocolrefprotocol = ExtensionLoader.getExtensionLoad...
    Ngcc阅读 3,952评论 0 2
  • 前面我们了解过了Java的SPI扩展机制,对于Java扩展机制的原理以及优缺点也有了大概的了解,这里继续深入一下D...
    加大装益达阅读 10,530评论 2 20
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,095评论 19 139
  • 早上七点就要把孩子送进学校了。女儿自上中学,我也一改往日作息习惯。过去晚间,生活上按排略为闲适些----检查...
    帕客阅读 3,060评论 0 1
  • Test test
    mx乐乐阅读 1,279评论 0 0

友情链接更多精彩内容