Dubbo源码学习(四ExtensionLoader 扩展点加载机制,Protocol$Adaptive,ProxyFactory$Adaptive,Cluster$Adaptive)
Posted 皓月行空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo源码学习(四ExtensionLoader 扩展点加载机制,Protocol$Adaptive,ProxyFactory$Adaptive,Cluster$Adaptive)相关的知识,希望对你有一定的参考价值。
坚持一下,把源码看完,勤奋一点,不要在懒惰了,你已经落下别人很多了
环境配置:
jdk 1.7.0.17
dubbo 2.5.x
myeclipse 2014
idea 2017
SPI注解的接口
在dubbo中,采用了类似于java的spi机制进行扩展类加载
在dubbo.jar文件夹下有个META-INF/dubbo/internal文件夹下,定义了很多了扩展点加载类,如下图
这些文件名基本是类的全路径名,所有扩展类交由ExtensionLoader来统计进行加载处理
ExtensionLoader的属性和方法
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\\\s*[,]+\\\\s*");
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
// ==============================
private final Class<?> type;
private final ExtensionFactory objectFactory;
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
private volatile Class<?> cachedAdaptiveClass = null;
private String cachedDefaultName;
private volatile Throwable createAdaptiveInstanceError;
private Set<Class<?>> cachedWrapperClasses;
private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
ExtensionLoader 对于外部调用来说,主要的方法是上图标注的3个方法,
我们以ServiceConfig为例,分析如下代码
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
ExtensionLoader.getExtensionLoader
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type)
if (type == null)
throw new IllegalArgumentException("Extension type == null");
if (!type.isInterface())
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
if (!withExtensionAnnotation(type))
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null)
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
return loader;
ExtensionLoader.getAdaptveExtension
public T getAdaptiveExtension()
Object instance = cachedAdaptiveInstance.get();
if (instance == null)
if (createAdaptiveInstanceError == null)
synchronized (cachedAdaptiveInstance)
instance = cachedAdaptiveInstance.get();
if (instance == null)
try
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
catch (Throwable t)
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
else
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
return (T) instance;
private T createAdaptiveExtension()
try
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
catch (Exception e)
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
private Class<?> getAdaptiveExtensionClass()
getExtensionClasses();
if (cachedAdaptiveClass != null)
return cachedAdaptiveClass;
return cachedAdaptiveClass = createAdaptiveExtensionClass();
private Class<?> createAdaptiveExtensionClass()
String code = createAdaptiveExtensionClassCode();
ClassLoader classLoader = findClassLoader();
com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
由此我们大体可以得到最终生成的Protocol类 是通过写死的字符串来编译生成相应的对象,也就基本上大体了解了ExtensionLoader.getAdaptiveExtension 获取的类是有字符串拼接构建的,下面提出几个比较重要的Adaptive类代码
Protocol$Adaptive
public class Protocol$Adaptive
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 Invoker refer(Class arg0, URL arg1) throws com.alibaba.dubbo.rpc.RpcException
if (arg1 == null) throw new IllegalArgumentException("url == null");
URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() +") use keys([protocol])");
Protocol extension = (Protocol) ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);
public Exporter export(Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
URL url = arg0.getUrl();
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name rom url(" + url.toString() + ") use keys([protocol])");
Protocol extension =(Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName);
return extension.export(arg0);
ProxyFactory$Adaptive
public class ProxyFactory$Adaptive implements com.alibaba.dubbo.rpc.ProxyFactory
public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("proxy", "javassist");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
ProxyFactory extension = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
return extension.getProxy(arg0);
public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, URL arg2) throws RpcException
if (arg2 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg2;
String extName = url.getParameter("proxy", "javassist");
if(extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
ProxyFactory extension =(ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
return extension.getInvoker(arg0, arg1, arg2);
Cluster$Adaptive
public class Cluster$Adaptive implements Cluster
public Invoker join(Directory arg0) throws RpcException
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("cluster", "failover");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url(" + url.toString() + ") use keys([cluster])");
Cluster extension =(Cluster) ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(extName);
return extension.join(arg0);
以上是关于Dubbo源码学习(四ExtensionLoader 扩展点加载机制,Protocol$Adaptive,ProxyFactory$Adaptive,Cluster$Adaptive)的主要内容,如果未能解决你的问题,请参考以下文章