2.3 Dubbo的适配器原理

在前面谈论Dubbo的分层架构时,我们讲到,Dubbo为每个功能点提供了一个SPI扩展接口,Dubbo框架在使用扩展点功能的时候是对接口进行依赖的,而一个扩展接口对应了一系列的扩展实现类。那么如何选择使用哪一个扩展接口的实现类呢?其实这是使用适配器模式来做的。

首先我们看看什么是适配器模式,比如Dubbo提供的扩展接口Protocol,其定义如下:

Dubbo会使用我们下一节将要讲解的动态编译技术为接口Protocol生成一个适配器类Protocol$Adaptive的对象实例,在Dubbo框架中需要使用Protocol的实例时,实际上就是使用Protocol$Adaptive的对象实例来获取具体的SPI实现类的,其代码如下:

在Dubbo框架中,protocol的定义为:private static final Protocol protocol=Extension-Loader.getExtensionLoader(Protocol.class).getAdaptiveExtension();,当调用protocol.export(wrapperInvoker)时,实际是调用Protocol$Adaptive的对象实例的export()方法,然后后者根据wrapperInvoker中URL里面的协议类型参数执行;代码2使用Dubbo增强SPI方法getExtension()获取对应的SPI实现类,然后调用代码3来执行具体SPI实现类的export()方法。

需要注意的是,在Dubbo中URL是一个核心概念,Dubbo框架把所需的参数都拼接到了URL对象里。这里假设代码2传递的协议类型为Dubbo,则说明使用增强SPI返回扩展接口Protocol的Dubbo实现,即返回了DubboProtocol的实例,那么代码3则返回调用DubboProtocol的export()方法的返回结果,也就是说当框架调用protocol.export(wrapperInvoker)时,实际上是调用了DubboProtocol的export()方法。

总结一下就是,适配器类Protocol$Adaptive会根据传递的协议参数的不同,加载不同的Protocol的SPI实现。

其实在Dubbo框架中,框架会给每个SPI扩展接口动态生成一个对应的适配器类,并根据参数来使用增强SPI以选择不同的SPI实现。比如扩展接口ProxyFactory的适配器类为ProxyFactory$Adaptive,其根据参数proxy来选择使用JdkProxyFactory还是使用JavassistProxyFactory做代理工厂;扩展接口Registry的适配器类Registry$Adaptive则根据参数register来决定使用ZookeeperRegistry、RedisRegistry、MulticastRegistry、DubboRegistry中的哪一个作为服务注册中心等。