26.泛化调用实现

看两个filter即可,剩下的filter下篇文章讲

GenericFilter

作用

先讨论一个问题,rpc,最简单的场景是consumer端调用provider端的一个服务,这个服务双方都遵循一个接口实现,按最简单的dubbo的demo玩法,是需要consumer和provider两段都要有这个接口声明的(包括接口参数的类型的相关类),比如:
org.simonme.dubbo.demo.provider.service.UserService.queryUser(int) 这是一个查询用户的服务接口,但是,如果consumer端没有这个服务的接口声明及其相关联的bean类,也就是如果仅仅在provider端能找到这个接口类,在consumer工程里压根没有这个类,那是否还能进行调用?
dubbo是可以的。 就是通过在proivder侧用GenericFilter达成目的。

使用方式

需要在consumer端声明这个bean的时候,加上generic="true"配置即可。

<dubbo:reference id="userService" interface="org.simonme.dubbo.demo.provider.service.UserService" generic="true">
</dubbo:reference>

generic还支持nativejava和bean两个可选的选项。nativejava对应byte[]类型的参数,bean对应com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor类型的参数。

此外在使用这个服务时,形式略有不同:

@Autowired
private GenericService userService;

@SuppressWarnings("static-access")
@Test
public void testSayHello()
{
    Object result = userService.$invoke("queryUser", new String[] { "int" },  new Object[]{100});
    System.out.println(result);
    System.out.println(result.getClass());
}

GenericService 表示你这个未知的服务类型,用$invoke这个特殊方法发起的你的服务方法调用。调用完之后,dubbo会把结果以hashmap的形式返回给你。比如,我这里是个User的bean,User有id和name字段,那么返回的map中就与id和value两个key,其对应的值就是bean的这两个字段的字段值。
为了便于理解,贴一下UserService的代码:

public interface UserService
{
    public User queryUser(@Range(min=0,message="用户id值不能小于0")int id);
}

上面这个写法,解释了怎么在consumer端没有org.simonme.dubbo.demo.provider.service.UserService接口声明的时候,调用他的queryUser方法。provider端无需改动,和正常写rpc服务一样配置即可。
用法也可以参见官方文档,使用泛化调用

实现原理

直接看GenericFilter代码,通过方法名(必须是$invoke),参数个数等判断是否命中,很简单,不再多说。

与Spring Cloud对比

Spring Cloud可以算有这个能力,因为Spring Cloud是http json的,http json天然不需要调用端有接口声明。

GenericImplFilter

作用

与 GenericFilter 类似,是一个相对的东西,他是用在provider端没有服务接口声明类时,使用的。使用方法可以参见官方文档实现泛化调用。不再多说。