我寫了個方法,可以給方法傳遞指定的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<String, ReferenceBean<?>> referenceConfigs = (ConcurrentMap<String, ReferenceBean<?>>) 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接口的文章: