我写了个方法,可以给方法传递指定的Dubbo接口名,方法名,参数值,方法来调用我们指定的Dubbo接口,并返回结果。
在SpringBoot中使用@Reference注解标识的Dubbo接口,比如:
@Reference
OrderService orderService;
这种接口的动态代理没有被放到Spring的上下文中,而是放在了Dubbo的处理类AnnotationBean中。
这种情况下使用
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
获取不到这个代理。
这种情下我们可以从Dubbo的AnnotationBean中获取动态代理对象。
下面是一个调用单参数接口的例子:
@Controller
@RequestMapping("/test")
public class TestController {
@Autowired
WebApplicationContext webApplicationContext;
/**
* @param interfaceName Dubbo接口名
* @param methodName 方法名
* @param parameter 参数值
* @return
*/
@RequestMapping(value = "/test1", method = RequestMethod.POST)
@ResponseBody
public Object test1(@RequestParam(value = "interfaceName") String interfaceName,
@RequestParam(value = "methodName") String methodName,
@RequestParam(value = "parameter") String parameter) {
Object result = null;
AnnotationBean annotationBean = (AnnotationBean) webApplicationContext.getBean("annotationBean");
try {
Field handlerField = annotationBean.getClass().getDeclaredField("referenceConfigs");
handlerField.setAccessible(true);
ConcurrentMap> referenceConfigs = (ConcurrentMap>) handlerField.get(annotationBean);
for (String key : referenceConfigs.keySet()) {
if (key.contains(interfaceName)) {
ReferenceBean referenceBean = referenceConfigs.get(key);
Object refer = referenceBean.get();
Class interfaceClass = referenceBean.getInterfaceClass();
Method[] methodArr = interfaceClass.getMethods();
for (int i = 0; i < methodArr.length; i++) {
Method m = methodArr[i];
if (m.getName().equals(methodName)
&& m.getGenericParameterTypes().length == 1) { // 命中方法,只校验了名字和参数数量
result = m.invoke(refer, new Object[]{parameter});
}
}
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
}
通过以上代码,我们可以这么传参数:
interfaceName:OrderService,或者com.test.OrderService。这是我们要调的接口名。
methodName:selectByCode。这是我们要调的接口名,假设OrderService中有selectByCode(String code)方法。
parameter:ABC123。这是我们要给方法传的参数。
注:
1,用@Autowired注解的WebApplicationContext是SpringBoot上下文的工具类。
2,annotationBean是Annotation在Spring上下文中注册的名字。
3,referenceConfigs是在Annotation中维护的一个Map,它的key是接口名,是这种格式的:
/com.test.OrderService:
前面有斜杠,后面有冒号。它的value则是ReferenceBean,是Dubbo接口动态代理的封装类。
4,ReferenceBean中的refer属性就是Dubbo生成的动态代理对象,可以通过referenceBean.get()方法来获得。
5,ReferenceBean中还记载了接口类的class,从而获得对应的Method。当我们有了Method,有了动态代理对象,有参数列表,就可以调用接口了。
6,上面的例子在匹配Method时,匹配的是单一字符串参数的接口,如果要匹配更多的参数模式,可以参考:
https://blog.csdn.net/lkforce/article/details/82693626
本文结束
三篇手动调用指定Dubbo接口的文章:
手动调用指定Dubbo接口(一)----Spring注入篇
手动调用指定Dubbo接口(二)----Reference篇
手动调用指定Dubbo接口(三)—GenericService篇