什么是泛化调用
通常我们想调用别人的服务时,我们需要在项目中引入对应的jar包。而泛化调用的作用是,我们无需依赖相关jar包,也能调用到该服务。
这个特性一般使用在网关类项目中,在业务开发中基本不会使用。
使用方式
假设我现在要调用下面的接口服务
package com.scj.demo.dubbo.provider.service.impl;
public interface ByeService {
String bye(String name);
}
api
ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(new ApplicationConfig("test"));
referenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
referenceConfig.setInterface("com.scj.demo.dubbo.provider.service.impl.ByeService");
referenceConfig.setGeneric(true);
GenericService genericService = referenceConfig.get();
Object result = genericService.$invoke(
"bye",
new String[]{"java.lang.String"},
new Object[]{"1234"});
System.out.println(result);
spring
在xml文件做以下配置
<dubbo:reference id="byeService" interface="com.scj.demo.dubbo.provider.service.impl.ByeService" generic="true" />
然后注入使用
@Service
public class PersonService {
@Resource(name = "byeService")
private GenericService genericService;
public void sayBye(){
Object result = genericService.$invoke(
"bye",
new String[]{"java.lang.String"},
new Object[]{"1234"});
System.out.println(result);
}
}
在两种调用方式中,我们都需要使用被调用接口的字符串参数生成GenericService,通过GenericService的$invoke间接调用目标接口的接口。
public interface GenericService {
/**
* Generic invocation
*
* @param method Method name, e.g. findPerson. If there are overridden methods, parameter info is
* required, e.g. findPerson(java.lang.String)
* @param parameterTypes Parameter types
* @param args Arguments
* @return invocation return value
* @throws Throwable potential exception thrown from the invocation
*/
Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
}
$invoke的三个参数分别为,方法名,方法参数类型数组,方法参数数组。
方法入参构造
可以看到泛化调用的一个复杂性在于$invoke的第三个参数的组装,下面介绍几种复杂入参的调用方式
首先丰富提供者接口
public interface ByeService {
String bye(String name);
String bye(String name, Long age, Date date);
String bye(Person person);
String bye(List<String> names);
String bye(String[] names);
String byePersons(List<Person> persons);
String byePersons(Person[] persons);
@Data
public static class Person{
private String name;
private Long age;
private Date birth;
}
public static void main(String[] args) {
System.out.println(Person.class.getName());
}
}
多参数
@Test
public void testMultiParam(){
result = genericService.$invoke(
"bye",
new String[]{"java.lang.String","java.lang.Long","java.util.Date"},
new Object[]{"scj",12L,new Date()});
System.out.println(result);
}
自定义对象
Map<String,Object> personMap = new HashMap<>();
{
personMap.put("name","scj");
personMap.put("age","12");
personMap.put("birth",new Date());
}
@Test
public void testPOJO(){
result = genericService.$invoke(
"bye",
new String[]{"com.scj.demo.dubbo.provider.service.impl.ByeService$Person"},
new Object[]{personMap});
System.out.println(result);
}
Map
@Test
public void testMap(){
result = genericService.$invoke(
"bye",
new String[]{"java.util.Map"},
new Object[]{personMap});
System.out.println(result);
}
集合
@Test
public void testList(){
List<String> names = Lists.newArrayList("scj1","scj2");
result = genericService.$invoke(
"bye",
new String[]{"java.util.List"},
new Object[]{names});
System.out.println(result);
}
数组
@Test
public void testArray(){
String[] nameArray = new String[]{"scj1","scj3"};
result = genericService.$invoke(
"bye",
new String[]{"java.lang.String[]"},
new Object[]{nameArray});
System.out.println(result);
}
集合+自定义对象
@Test
public void testPOJOList(){
result = genericService.$invoke(
"byePersons",
new String[]{"java.util.List"},
new Object[]{Lists.newArrayList(personMap,personMap)});
System.out.println(result);
}
数组+自定义对象
@Test
public void testPOJOArray(){
result = genericService.$invoke(
"byePersons",
new String[]{"com.scj.demo.dubbo.provider.service.impl.ByeService$Person[]"},
new Object[]{Lists.newArrayList(personMap,personMap)});
System.out.println(result);
}
结果返回
与入参相似,虽然$invoke的返回定义为Object,实际上针对不同类型有不同的返回。
网友评论