什么是自适应机制
上篇讲解Dubbo SPI机制的文章中提到,Dubbo里可以通过ExtensionLoader.getExtensionLoader(XXXClass).getExtension(key)的形式来获取接口的某个实现类。
但这种形式本质上还是通过硬编码的形式在代码中固定的获取了接口的一个实现,诸如Protocol(实现有Dubbo、Redis、Thrift等),或者Transporter(实现有Netty、Mina等)这些接口,我们是可以在Dubbo服务声明时指定具体实现的。如图所示:
那么Dubbo是如何实现根据用户指定的参数来找到对应的接口实现类的呢?
先给出结论:Dubbo接口在拓展方法被调用时,根据运行时参数(URL中参数)动态生成接口的Adaptive自适应拓展类,在生成的拓展方法中根据URL中用户指定的参数key,调用ExtensionLoader.getExtensionLoader(XXXClass).getExtension(key)来获取具体的实现类
那么上面提到的运行时动态生成的拓展类代码是什么样的呢?以Protocol接口为例
先看下包含自适应方法的Protocol接口定义,export
,refer
是2个自适应的方法(用 @Adaptive
注解修饰)
@SPI("dubbo")
public interface Protocol {
int getDefaultPort();
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
void destroy();
}
Protocol接口生成的自适应扩展类,类名为Protocol$Adaptive
,代码如下
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy()" +
" of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {
throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol" +
".getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}
public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
if (arg1 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.UR