美文网首页
Dubbo自定义标签和扩展点

Dubbo自定义标签和扩展点

作者: 是我_7b3f | 来源:发表于2018-05-21 16:08 被阅读0次

           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的扩展点实例,这里我们可以实现自己的逻辑。

    相关文章

      网友评论

          本文标题:Dubbo自定义标签和扩展点

          本文链接:https://www.haomeiwen.com/subject/nsnzdftx.html