什么是泛化調用?
泛化調用就是服務消費者端因為某種原因並沒有該服務接口,這個原因有很多,比如是跨語言的,一個PHP工程師想調用某個java接口,他並不能按照你約定,去寫一個個的接口,Dubbo並不是跨語言的RPC框架,但並不是不能解決這個問題,這個PHP程序員搭建了一個簡單的java web項目,引入了dubbo的jar包,使用dubbo的泛化調用,然后利用web返回json,這樣也能完成跨語言的調用。泛化調用的好處之一就是這個了。
簡而言之,泛化調用,最最直接的表現就是服務消費者不需要有任何接口的實現,就能完成服務的調用。
為什么要使用泛化調用?
一般使用dubbo,provider端需要暴露出接口和方法,consumer端要十分明確服務使用的接口定義和方法定義(還有入參返參類型等等信息,常常還需要基於provider端提供的API),兩端才能正常通信調用。
然而存在一種使用場景,調用方並不關心要調用的接口的詳細定義,它只關注我要調用哪個方法,需要傳什么參數,我能接收到什么返回結果即可,這樣可以大大降低consumer端和provider端的耦合性。
所以為了應對以上的需求,dubbo提供了泛化調用,也就是在consumer只知道一個接口全限定名以及入參和返參的情況下,就可以調用provider端的調用,而不需要傳統的接口定義這些繁雜的結構。
泛化調用使用的是GenericService接口
一、示例
(1)服務提供者
public interface TestService { List<String> getListById(Long id); } public class TestServiceImpl implements TestService { @Override public List<String> getListById(Long id) { List<String> list = new ArrayList<String>(); list.add("test1-" + id); list.add("test2-" + id); list.add("test3-" + id); return list; } }
<dubbo:service retries="0" interface="com.generic.TestService" ref="testService"/>
服務提供者沒有任何變化
(2)服務消費者
需要配置一個generic="true"
<dubbo:reference id="testService" interface="com.generic.TestService" generic="true"/>
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"}); GenericService testService = (GenericService) context.getBean("testService"); Object result = testService.$invoke("getListById", new String[] { "java.lang.Long" }, new Object[]{ "666" }); System.out.println(result); }
二、不依賴spring配置文件
我們剛才說,一個PHP程序員想要搭建一個簡單的web項目,可是你卻叫他依賴於spring的配置文件,對他難度是不小的,dubbo也幫你想到了,泛型調用,服務消費端可以不依賴spring的配置文件,我們重新寫下測試類Consumer
public static void main(String[] args) { // 普通編碼配置方式 ApplicationConfig application = new ApplicationConfig(); application.setName("dubbo-consumer"); // 連接注冊中心配置 RegistryConfig registry = new RegistryConfig(); registry.setAddress("zookeeper://127.0.0.1:2181"); ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); reference.setApplication(application); reference.setRegistry(registry); reference.setInterface("com.generic.TestService"); reference.setGeneric(true); // 聲明為泛化接口 ReferenceConfigCache cache = ReferenceConfigCache.getCache(); GenericService genericService = cache.get(reference); // 基本類型以及Date,List,Map等不需要轉換,直接調用 Object result = genericService.$invoke("getListById", new String[] { "java.lang.Long" }, new Object[] { 1L }); System.out.println(result); }
泛化調用可以方便用戶對dubbo服務消費者端的擴展,可以方便,豐富了服務消費者的調用方式,甚至可以做變相的Rest調用,這些都是可以的,不過,它的缺點也是很明顯的,參數傳遞復雜,不方便使用。但是這種方式是不能缺失的