Dubbo Version: 2.7.7
@SPI
public interface RouterFactory {
/**
* Create router.
* Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility.
*
* @param url url
* @return router instance
*/
@Adaptive("protocol")
Router getRouter(URL url);
}
@Adaptive
注解是放在方法上面的,而且value是protocol,表示在调用方法的时候根据URL的protocol动态加载所需RouterFactory
并创建Router
public class AdapteExtendsionTest {
private static final RouterFactory ROUTER_FACTORY = ExtensionLoader.getExtensionLoader(RouterFactory.class)
.getAdaptiveExtension();
public static void main(String[] args) {
Router router = ROUTER_FACTORY.getRouter(URL.valueOf(
"condition://0.0.0.0/com.leimo.demo.DemoService?category=routers&dynamic=false&enabled=true&force=true&group=test&name=null&priority=0&router=condition&rule=host+%3D+4.3.2.1+%26+host+%21%3D+1.2.3.4+%3D%3E+false&runtime=false&version=1.0"));
System.out.println(router.getClass().getName());
}
}
ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension()
本质就是动态拼接java类字符串,然后用javassist
动态编译成class
拼接生成的类如下
package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class RouterFactory$Adaptive implements org.apache.dubbo.rpc.cluster.RouterFactory {
public org.apache.dubbo.rpc.cluster.Router getRouter(org.apache.dubbo.common.URL arg0) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg0;
String extName = url.getProtocol();
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.cluster.RouterFactory) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.cluster.RouterFactory extension = (org.apache.dubbo.rpc.cluster.RouterFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.cluster.RouterFactory.class).getExtension(extName);
return extension.getRouter(arg0);
}
}
当调用接口的getRouter方法时,底层调用的是生成的RouterFactory$Adaptive
的getRouter
方法,方法逻辑很简单
就是获取URL的protocol,我们测试代码使用的url的protocol是condition
,所以extName
是condition
,
RouterFactory SPI文件
file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory
script=org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory
condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory
app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory
tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory
所以加载的是ConditionRouterFactory
参考文章:
自适应拓展机制
网友评论