interface com.alibaba.dubbo.cache.CacheFactory interface com.alibaba.dubbo.common.compiler.Compiler interface com.alibaba.dubbo.common.extension.ExtensionFactory interface com.alibaba.dubbo.common.serialize.Serialization interface com.alibaba.dubbo.common.store.DataStore interface com.alibaba.dubbo.common.threadpool.ThreadPool interface com.alibaba.dubbo.monitor.MonitorFactory interface com.alibaba.dubbo.registry.RegistryFactory interface com.alibaba.dubbo.remoting.Codec2 interface com.alibaba.dubbo.remoting.Dispatcher interface com.alibaba.dubbo.remoting.Transporter interface com.alibaba.dubbo.remoting.exchange.Exchanger interface com.alibaba.dubbo.remoting.telnet.TelnetHandler interface com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter interface com.alibaba.dubbo.rpc.ExporterListener interface com.alibaba.dubbo.rpc.Filter interface com.alibaba.dubbo.rpc.InvokerListener interface com.alibaba.dubbo.rpc.Protocol interface com.alibaba.dubbo.rpc.ProxyFactory interface com.alibaba.dubbo.rpc.cluster.Cluster interface com.alibaba.dubbo.rpc.cluster.ConfiguratorFactory interface com.alibaba.dubbo.rpc.cluster.LoadBalance interface com.alibaba.dubbo.rpc.cluster.RouterFactory interface com.alibaba.dubbo.validation.Validation
@SPI("ali") // 默认的值支付宝支付
public interface Pay {
// 接口的方法需要添加这个注解,在测试代码中,参数至少要有一个URL类型的参数
@Adaptive({"paytype"}) // 付款方式
void pay(URL url);
}
public class AliPay implements Pay {
@Override
public void pay(URL url) {
System.out.println("使用支付宝支付");
}
}
public class WechatPay implements Pay {
@Override
public void pay(URL url) {
System.out.println("使用微信支付");
}
}
在/dubbo-common/src/main/resources/META-INF/services/com.test.Pay文件下添加内容如下:
wechat = com.test.WechatPay
ali = com.test.AliPay
说明:Adaptive 可注解在类或方法上。当 Adaptive 注解在类上时,Dubbo 不会为该类生成代理类。注解在方法(接口方法)上时,Dubbo 则会为该方法生成代理逻辑。Adaptive 注解在类上的情况很少,在 Dubbo 中,仅有两个类被 Adaptive 注解了,分别是 AdaptiveCompiler 和 AdaptiveExtensionFactory。此种情况,表示拓展的加载逻辑由人工编码完成。更多时候,Adaptive 是注解在接口方法上的,表示拓展的加载逻辑需由框架自动生成。Adaptive 注解的地方不同,相应的处理逻辑也是不同的。
public static void main(String[] args) { ExtensionLoader<Pay> loader = ExtensionLoader.getExtensionLoader(Pay.class); Pay pay = loader.getAdaptiveExtension(); pay.pay(URL.valueOf("http://localhost:9999/xxx")); // 使用支付宝支付 pay.pay(URL.valueOf("http://localhost:9999/xxx?paytype=wechat")); // 使用微信支付 }
这里也会生成一个代理类 PayService$Adaptive,这种代理类实现AOP功能
package com.test; import com.alibaba.dubbo.common.extension.ExtensionLoader; public class PayService$Adaptive implements com.test.PayService { public void pay(com.alibaba.dubbo.common.URL arg0) { if (arg0 == null) throw new IllegalArgumentException("url == null"); com.alibaba.dubbo.common.URL url = arg0; // 1.从 URL 中获取指定的SPI的扩展名称 String extName = url.getParameter("paytype", "ali"); // 从URL中获取key为paytype参数的value,如果获取不到,则使用默认@SPI注解上的值 if(extName == null) throw new IllegalStateException("Fail to get extension(com.test.PayService) name from url(" + url.toString() + ") use keys([0])"); // 2.通过 SPI 加载具体的实现类 com.test.PayService extension = (com.test.PayService)ExtensionLoader.getExtensionLoader(com.test.PayService.class) .getExtension(extName); // 3.调用目标方法 extension.pay(arg0); } }
PayService wechatPay = extensionLoader.getExtension("wechatPay");
wechatPay.pay(20);
PayService payService = extensionLoader.getAdaptiveExtension();
payService.pay(url);
public class ReferenceConfig<T> extends AbstractReferenceConfig { // 类在加载阶段这个值为 ProxyFactory$Adaptive类型 private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); private T createProxy(Map<String, String> map) { // 省略若干代码... return (T) proxyFactory.getProxy(invoker); } }
com.alibaba.dubbo.common.URL url = invoker.getUrl(); String extName = url.getParameter("proxy", "javassist"); ProxyFactory extension = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(extName);
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); }
codeBuidler.append("package " + type.getPackage().getName() + ";");
codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";");
codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adaptive" + " implements " + type.getCanonicalName() + " {");
//value代表@Adaptive注解中的参数,defaultExtName是@SPI注解参数 getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName); // 例如: String getNameCode = String.format("url.getParameter(\"%s\")", "dubbo"); // 结果为url.getParameter("dubbo")
code.append("\nString extName = ").append(getNameCode).append(";");
// check extName == null?
String s = String.format("\nif(extName == null) " +
"throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");",
type.getName(), Arrays.toString(value));
code.append(s);
s = String.format("\n%s extension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",
type.getName(), ExtensionLoader.class.getSimpleName(), type.getName());
code.append(s);
Dubbo之扩展机制(二)Adaptive【URL-动态适配】
原文:https://www.cnblogs.com/caoxb/p/13140329.html