dubbo里面的GenericService干啥的

两个用途一直是泛化服务,一种是泛化引用。前者是为了provider省事,后者是消费者省事。先介绍泛化服务怎么做到的:

比如提供者想省事,虽然提供了10个方法,但是不想在接口里面写十个方法,也就不用给这十个方法做函数声明、参数声明了。直接通过:

ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
        service.setApplication(new ApplicationConfig("generic-provider"));
        service.setRegistry(new RegistryConfig("N/A"));
        service.setProtocol(new ProtocolConfig("dubbo", 29581));
        service.setInterface(DemoService.class.getName());
        service.setRef(new GenericService() {

            public Object $invoke(String method, String[] parameterTypes, Object[] args)
                    throws GenericException {
                if ("sayName".equals(method)) {
                    return "Generic " + args[0];
                }
                if ("throwDemoException".equals(method)) {
                    throw new GenericException(DemoException.class.getName(), "Generic");
                }
                if ("getUsers".equals(method)) {
                    return args[0];
                }
                return null;
            }
        });
        service.export();

  也就是通过method不同,直接返回不同处理结果,隐藏了方法和参数声明。上面虽然 service.setInterface(DemoService.class.getName()),这里传入的是接口的str名称。也就是说通过generic,provider已经完全不依赖interface了,只是用到这个接口的名称字符串用做servericekey用的。

 

之所以能这样操作,消费者在调用的时候,需要在url里面指定generic=true,那么在经过filter链的时候,在GenericImplFilter会做generic处理

把method-name设置成$invoke

parameter-types由于提供者不一定有,于是传入类型的string类型。

args按照pojo或者java-bean进行序列化成一个map,里面指定了参数的class类型、每个filed的value。

 

provider不会把这个map做逆序列化处理,直接原样返回这个map,所以可以看到这个generic的provider能够处理的东西比较有限。消费者在得到结果的时候,依然是一个map,那么在GenericImplFilter里面,把invoke得到的结果逆序列化成具体的对象。也就是说由GenericImplFilter序列化成一个map,你自己负责逆序列化。

 

 

 

对于泛化引用的话,例子如下:

 

ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
            reference.setApplication(new ApplicationConfig("generic-consumer"));
            reference.setInterface(DemoService.class);
            reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
            reference.setGeneric(true);
            GenericService genericService = reference.get();
            try {
                List<Map<String, Object>> users = new ArrayList<Map<String, Object>>();
                Map<String, Object> user = new HashMap<String, Object>();
                user.put("class", "com.alibaba.dubbo.config.api.User");
                user.put("name", "actual.provider");
                users.add(user);
                users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[]{List.class.getName()}, new Object[]{users});
                

  

消费者直接使用$invoke方法,不用考虑provider到底提供了哪些方法,通过字符串getuser调用,参数类型也不用关心,直接用map描述参数的类型和value。

provider在被调用的时候,还是GenericImplFilter这个filter里面,由provider通过map进行逆序列化,毕竟provider提供的方法里面是按照这个参数类型进行处理的,所以必须从map转化成真正的类型,处理完成以后,还要逆序列化成map才能返回给consumer,因为consumer只认识map,不认识具体参数类型。

 

posted @ 2018-12-16 20:41  notlate  阅读(5973)  评论(0编辑  收藏  举报