泛化接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值之中的所有POJO均用Map表示,通常用于框架集成。
Spring方式
xml配置支持泛化
<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />
java实现泛化调用
GenericService barService = (GenericService) applicationContext.getBean("barService");
Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });
Api方式
import org.apache.dubbo.rpc.service.GenericService;
...
// 引用远程服务
// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.xxx.XxxService");
reference.setVersion("1.0.0");
// 声明为泛化接口
reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("sayHello", new String[] {"java.lang.String"}, new Object[] {"world"});
// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map<String, Object> person = new HashMap<String, Object>();
person.put("name", "xxx");
person.put("password", "yyy");
// 如果返回POJO将自动转成Map
Object result = genericService.$invoke("findPerson", new String[]
{"com.xxx.Person"}, new Object[]{person});
实现GenericService接口方式
声明接口为泛化除了标签配置,还可以通过实现GenericService接口
正常如:
<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />
实现接口:
package com.foo;
public class MyGenericService implements GenericService {
public Object $invoke(String methodName, String[] parameterTypes, Object[] args) throws GenericException {
if ("sayHello".equals(methodName)) {
return "Welcome " + args[0];
}
}
}
<bean id="genericService" class="com.foo.MyGenericService" />
<dubbo:service interface="com.foo.BarService" ref="genericService" />
ReferenceConfig缓存
ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,需要缓存。否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄露,dubbo提供了简单的工具类ReferenceConfigCache用于缓存。
ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>();
reference.setInterface(XxxService.class);
reference.setVersion("1.0.0");
......
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
// cache.get方法中会缓存 Reference对象,并且调用ReferenceConfig.get方法启动ReferenceConfig
XxxService xxxService = cache.get(reference);
// 注意! <span style="color: #ff0000;">Cache会持有ReferenceConfig,不要在外部再调用ReferenceConfig的destroy方法,导致Cache内的ReferenceConfig失效!</span>
// 使用xxxService对象
xxxService.sayHello();
注(释放资源,执行泛化调用过程中会出现服务 ReferenceConfigCache.getCache().get(reference)为null的情况,需要用到以下代码):
消除Cache中的referenceConfig,将销毁ReferenceConfig并释放对应的资源
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
cache.destroy(reference);
另附利用dubbo泛化调用特性做的网关服务项目地址: