dubbo中动态加载机制SPI使得运行时代理工厂poxyFactory和协议protocol等可以根据配置而动态变化。
ServiceConfig中poxyFactory和protocol就很好的运用了SPI,
//ServiceConfig中poxyFactory和protocol
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
由于源码中很难清晰的捕获到adaptiveExtension类的code,故adaptive类的具体实心仍然比较模糊,adaptiveExtension的生成默认使用的Javassit字节码编辑工具,可以调用CtClass的writeFile()方法生成相应的adaptive类文件;
//ExtensionLoader中AdaptiveExtensionClass的创建
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);
}
/**
*Compiler默认使用javassist的实现,对应的实现类是JavassistCompiler(路径META-*INF\dubbo\internal\com.alibaba.dubbo.common.compiler.Compiler中找到key为javassist的类全路径是com.alibaba.dubbo.common.compiler.support.JavassistCompiler)
*/
@SPI("javassist")
public interface Compiler {
Class<?> compile(String code, ClassLoader classLoader);
}
ProxyFactory$Adaptive反编译后code
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.Node;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Adaptive
implements ProxyFactory
{
public Object getProxy(Invoker paramInvoker)
throws RpcException
{
if (paramInvoker == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (paramInvoker.getUrl() == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
URL localURL = paramInvoker.getUrl();
String str = localURL.getParameter("proxy", "javassist");
if (str == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + localURL.toString() + ") use keys([proxy])");
ProxyFactory localProxyFactory = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(str);
return localProxyFactory.getProxy(paramInvoker);
}
public Invoker getInvoker(Object paramObject, Class paramClass, URL paramURL)
throws RpcException
{
if (paramURL == null)
throw new IllegalArgumentException("url == null");
URL localURL = paramURL;
String str = localURL.getParameter("proxy", "javassist");
if (str == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + localURL.toString() + ") use keys([proxy])");
ProxyFactory localProxyFactory = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(str);
return localProxyFactory.getInvoker(paramObject, paramClass, paramURL);
}
}
Protocol$Adaptive反编译后的code
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.Node;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Adaptive
implements 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 Invoker refer(Class paramClass, URL paramURL)
throws RpcException
{
if (paramURL == null)
throw new IllegalArgumentException("url == null");
URL localURL = paramURL;
String str = (localURL.getProtocol() == null) ? "dubbo" : localURL.getProtocol();
if (str == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + localURL.toString() + ") use keys([protocol])");
Protocol localProtocol = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(str);
return localProtocol.refer(paramClass, paramURL);
}
public Exporter export(Invoker paramInvoker)
throws RpcException
{
if (paramInvoker == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (paramInvoker.getUrl() == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
URL localURL = paramInvoker.getUrl();
String str = (localURL.getProtocol() == null) ? "dubbo" : localURL.getProtocol();
if (str == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + localURL.toString() + ") use keys([protocol])");
Protocol localProtocol = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(str);
return localProtocol.export(paramInvoker);
}
}