前言
大家好,今天开始给大家分享 — Dubbo 专题之 Dubbo 泛化引用。在前一个章节中我们介绍了 Dubbo 中的参数验证以及使用场景。我们在这个章节会继续介绍 Dubbo 泛化引用。那么什么是泛化引用呢?泛化引用有什么作用呢?下面就让我详细了解下吧!
1. 泛化引用简介
在前面的章节中我们编写的 Dubbo 服务都是基于 API 接口,例如:com.muke.dubbocourse.common.api.BookFacade
接口。我们在日常开发中的步骤都是首先定义好暴露服务的 API 接口,然后把这个接口打包成 jar 提供给服务调用方。也就是说通常情况下我们的服务调用方都会依赖我们定义的 API 接口编程。那么在 Dubbo 中为我们提供一种不需要依赖 API 接口的方式进行服务调用,这种方式就泛化引用。其表示类为GenericService
。
2. 使用方式
在这里我们主要介绍两种使用方式:
通过 Spring 使用泛化引用
<dubbo:reference id="barService" interface="com.muke.dubbocourse.common.api.BookFacade" generic="true" />
复制代码
GenericService barService = (GenericService) applicationContext.getBean("bookFacade");
Object result = barService.$invoke("queryAll", null, null);
复制代码
通过 Java API 方式使用
// 引用远程服务
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.muke.dubbocourse.common.api.BookFacade");
reference.setVersion("0.0.1");
// 声明为泛化接口
reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
// 如果返回实体对象将自动转成Map
Object result = genericService.$invoke("queryByName",new String[]
{"com.muke.dubbocourse.common.api.RequestParameter"}, new Object[]{parameter});
复制代码
3. 使用场景
从泛化引用本身我们可以知道它是不需要 API 接口,也就是说泛化引用使用场景在服务提供方没有明确的 API 接口提供的情况下我们都可以使用。通常用于框架集成,比如:实现一个 Dubbo 服务对外统一网,就可通过 GenericService
调用后端所有服务实现。 例如:
在上面的图中客户端通过统一的 Dubbo 网关访问后端所有的 Dubbo 服务,这里就是使用 泛化调用实现。
4. 示例演示
下面我们通过两种方式来演示一个获取图书列表的服务。
使用 Spring 泛化引用
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-consumer" logger="log4j"/>
<!--使用zookeeper注册中心-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!--设置generic="true"-->
<dubbo:reference id="bookFacade" interface="com.muke.dubbocourse.common.api.BookFacade" generic="true"></dubbo:reference>
</beans>
复制代码
public class XmlApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("generic/consumer/spring/dubbo-consumer-xml.xml");
context.start();
//创建泛化调用对象
GenericService bookFacade = (GenericService) context.getBean("bookFacade");
RequestParameter parameter = new RequestParameter();
parameter.setName("SpringBoot");
//泛化调用 第一个参数:方法名称,第二个参数:请求参数类型的数组,第三方个参数:请求参数值的数组
Object result = bookFacade.$invoke("queryByName", new String[] { "com.muke.dubbocourse.common.api.RequestParameter" }, new Object[] { parameter });
System.out.println("Result=>"+result);
System.in.read();
}
}
复制代码
使用 Java API 方式
public class XmlApplication2 {
public static void main(String[] args) throws IOException {
// 引用远程服务
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
// 弱类型接口名
reference.setInterface("com.muke.dubbocourse.common.api.BookFacade");
//注册中心配置
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("zookeeper://127.0.0.1:2181");
reference.setRegistry(registryConfig);
//应用配置
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-consumer");
reference.setApplication(applicationConfig);
// 声明为泛化接口
reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
RequestParameter parameter = new RequestParameter();
parameter.setName("SpringBoot");
Object result = genericService.$invoke("queryByName", new String[]{"com.muke.dubbocourse.common.api.RequestParameter"}, new Object[]{parameter});
System.out.println("Result=>" + result);
System.in.read();
}
}
复制代码
在上面的代码中我们通过 Java API 的方式配置了注册中心、应用配置。在调用服务的使用和上面的 Spring 使用方式类似使用org.apache.dubbo.rpc.service.GenericService#$invoke
方法。
5. 实现原理
在上面的代码GenericService genericService = reference.get()
中会调用到org.apache.dubbo.config.ReferenceConfig#init
方法,而在此方法中org.apache.dubbo.config.ReferenceConfig#createProxy
方法创建一个服务调用代理对象。当我们调用genericService.$invoke
方法是实际调用的是org.apache.dubbo.rpc.proxy.InvokerInvocationHandler#invoke
方法然后调用org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker#invoke
调用我们org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke
在此方法中就查找我们的调用远程的 Invoker 对象,时序图如下:
6. 小结
在本小节中我们主要学习了 Dubbo 中泛化引用和使用场景,以及使用 Spring 的方式和基于 Java API 的方式使用泛化引用。同时也分析了泛化引用实现的原理,其实就是通过ReferenceConfig
包装接口名称、调用方法以及参数名称和参数值,再创建GenericService
代理对象然后调用一系列的 Invoker
对象。
本节课程的重点如下:
理解 Dubbo 中泛化引用
了解了两种泛化引用使用方式
了解泛化引用实现原理
了解泛化引用使用场景
作者
个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年 IT 男 获取最新技术文章推送!
博客地址: http://youngitman.tech
微信公众号:
评论