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