泛化调用

本篇文章主要介绍dubbo的泛化调用。主要知识点如下:

  • 什么是泛化调用
  • 如何使用泛化调用
  • 泛化调用原理
    什么是泛化调用泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,这是官方的说法,对于新人我认为太抽象了,这里解释一下。我们在做正常的dubbo调用时,服务端会提供一个所有接口的jar包让客户端引入,此时客户端就知道服务端提供了哪些接口并进行使用,参考 如何搭建并进行调用,而对于泛化调用,我们还是需要知道服务端提供了哪些接口,只不过是程序不知道而已,此时我们在程序中使用泛化调用,显示填入需要调用的接口名称,dubbo会进行匹配并进行调用后返回。
    如何使用泛化调用上面介绍了泛化调用的概念,这里介绍一下如何使用。
    假设服务端提供如下接口
    package com.example.dubboprovider.rpc; public interface CityService { String getCityName(); }

    泛化调用最重要的就是 GenericService,首先我们定义一个服务引用
    @Reference(interfaceName = "com.example.dubboprovider.rpc.CityService", generic = true) GenericService genericService;

    上面的代码里定义了一个 GenericService,注意上面的注解 @Reference,在之前的文章中说到过这个注解表明是一个dubbo引用,注解里面 interfaceName 用来表明你要使用的接口类,generic 为true用来表明是泛化调用,这样一个泛化接口就完成了。
    再来看下调用
    Object name = genericService.$invoke("getCityName", new String[]{}, new Object[]{});

    通过以上几个步骤,一个简单的泛化调用就完成了。
    原理顺着上面的例子讲述,介绍一下泛化调用的原理。
    首先引用服务(参考服务调用过程解析,后面会写),dubbo会为上面定义的 genericService 生成一个代理类,在代码逻辑 genericService.$invoke 的时候就会走到dubbo生成的代理类中。在讲 dubbo filter 的时候我们讲到dubbo内置了一些filter,其中就有两个filter分别叫做 GenericImplFilterGenericFilter
    GenericImplFilter
    泛化调用
    文章图片

    GenericFilter
    泛化调用
    文章图片

    这两个filter就是对泛化调用的处理,其中 GenericImplFilter 是消费端的处理,而 GenericFilter 是服务端的处理。消费端的处理就是对参数做一些预处理(非内置的进行序列化、以及获得结果之后的反序列化,内置的进行校验以及传递generic值),而服务端的处理就是对内置的泛化调用进行处理(序列化以及返序列化),从逻辑中我们可以看到其实 generic 可以有三种赋值方式,分别为true、nativejava以及bean,其实就是对应的对于我们传递的参数的解析方式,下面分别介绍一下:
  • true
    这个是最简单的处理方式,dubbo内置的PojoUtils工具类就会进行解析。
  • nativejava
    如果参数是byte数组类型的,则我们可以通过实现 Serialization 接口来自定义实现序列化和反序列化。
  • bean
    如果你的参数类继承JavaBeanDescriptor,则可以通过该种方式来转换对象。
    dubbo内置的类型转换已经很全了,如果你有自己的转换需求,可以考虑在这一块进行改造。
    从源码中我们也可以看出来,其实泛化调用就是通过filter过滤对传递的参数进行了一层转换,然后找到匹配的接口以及方法进行调用。
    总结【泛化调用】泛化调用确实是一种非常灵活的方式,其实现也很简单,但是对于调用者来说,相对普通调用显得麻烦一些。在实际业务中,我们可以结合具体场景使用泛化调用,比如测试、网关路由等。

    推荐阅读