手動調用指定Dubbo接口(二)----Reference篇

我寫了個方法,可以給方法傳遞指定的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接口的文章:

手動調用指定Dubbo接口(一)----Spring注入篇

手動調用指定Dubbo接口(二)----Reference篇

手動調用指定Dubbo接口(三)—GenericService篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章